溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Android Surface理解

發(fā)布時間:2020-06-07 16:56:17 來源:網(wǎng)絡(luò) 閱讀:30692 作者:lindt 欄目:移動開發(fā)

結(jié)合別人的博客和自己看的代碼,梳理下自己對surface的理解

1.代碼相關(guān)文件

/AOSP/frameworks/native/libs/uiAndroid Surface理解

主要是bufferqueuecore與surfaceflinger中分配

GraphicBufferAllocator 通過hw_get_module()&gralloc_open與硬件提供的設(shè)備交互
ex: /hardware/qcom/display/libgralloc/alloc_controller.cpp etc.


/AOSP/frameworks/native/libs/gui

Android.mk                   IGraphicBufferAlloc.cpp
BitTube.cpp                  IGraphicBufferConsumer.cpp
BufferItemConsumer.cpp       IGraphicBufferProducer.cpp
BufferItem.cpp               IProducerListener.cpp
BufferQueueConsumer.cpp      ISensorEventConnection.cpp
BufferQueueCore.cpp          ISensorServer.cpp
BufferQueue.cpp              ISurfaceComposerClient.cpp
BufferQueueProducer.cpp      ISurfaceComposer.cpp
BufferSlot.cpp               LayerState.cpp
CleanSpec.mk                 Sensor.cpp
ConsumerBase.cpp             SensorEventQueue.cpp
CpuConsumer.cpp              SensorManager.cpp
DisplayEventReceiver.cpp     StreamSplitter.cpp
GLConsumer.cpp               SurfaceComposerClient.cpp
GraphicBufferAlloc.cpp       SurfaceControl.cpp
GuiConfig.cpp                Surface.cpp
IConsumerListener.cpp        SyncFeatures.cpp
IDisplayEventConnection.cpp  tests

SurfaceComposerClient 中成員變量 sp<ISurfaceComposerClient>  mClient;與surface.cpp binder通信

/AOSP/frameworks/native/services/surfaceflinger

Android.mk         EventControlThread.cpp   MODULE_LICENSE_APACHE2
Barrier.h          EventControlThread.h     MonitoredProducer.cpp
Client.cpp         EventLog                 MonitoredProducer.h
Client.h           EventThread.cpp          RenderEngine
clz.h              EventThread.h            SurfaceFlingerConsumer.cpp
Colorizer.h        FrameTracker.cpp         SurfaceFlingerConsumer.h
DdmConnection.cpp  FrameTracker.h           SurfaceFlinger.cpp
DdmConnection.h    Layer.cpp                SurfaceFlinger.h
DisplayDevice.cpp  LayerDim.cpp             surfaceflinger.rc
DisplayDevice.h    LayerDim.h               tests
DisplayHardware    Layer.h                  Transform.cpp
DispSync.cpp       main_surfaceflinger.cpp  Transform.h
DispSync.h         MessageQueue.cpp
Effects            MessageQueue.h

surfaceflinger管理surface及l(fā)ayer

AOSP/frameworks/base/core/java/android/view

AbsSavedState.java                       MagnificationSpec.aidl
accessibility                            MagnificationSpec.java
AccessibilityInteractionController.java  MenuInflater.java
AccessibilityIterators.java              MenuItem.java
ActionMode.java                          Menu.java
ActionProvider.java                      MotionEvent.aidl
animation                                MotionEvent.java
AnimationRenderStats.aidl                OrientationEventListener.java
Choreographer.java                       OrientationListener.java
CollapsibleActionView.java               package.html
ContextMenu.java                         PointerIcon.aidl
ContextThemeWrapper.java                 PointerIcon.java
DisplayAdjustments.java                  RemotableViewMethod.java
Display.aidl                             RenderNodeAnimator.java
DisplayEventReceiver.java                RenderNode.java
DisplayInfo.aidl                         ScaleGestureDetector.java
DisplayInfo.java                         SearchEvent.java
Display.java                             SoundEffectConstants.java
DisplayListCanvas.java                   SubMenu.java
DragEvent.aidl                           Surface.aidl
DragEvent.java                           SurfaceControl.java
FallbackEventHandler.java                SurfaceHolder.java
FocusFinderHelper.java                   Surface.java
FocusFinder.java                         SurfaceSession.java
FrameInfo.java                           SurfaceView.java
FrameStats.java                          textservice
GestureDetector.java                     TextureView.java
GhostView.java                           ThreadedRenderer.java
GraphicBuffer.aidl                       TouchDelegate.java
GraphicBuffer.java                       VelocityTracker.java
Gravity.java                             ViewAnimationUtils.java
HapticFeedbackConstants.java             ViewConfiguration.java
HardwareLayer.java                       ViewDebug.java
HardwareRenderer.java                    ViewGroup.java
IApplicationToken.aidl                   ViewGroupOverlay.java
IAssetAtlas.aidl                         ViewHierarchyEncoder.java
IGraphicsStats.aidl                      View.java
IInputFilter.aidl                        ViewManager.java
IInputFilterHost.aidl                    ViewOutlineProvider.java
InflateException.java                    ViewOverlay.java
InputChannel.aidl                        ViewParent.java
InputChannel.java                        ViewPropertyAnimator.java
InputDevice.aidl                         ViewPropertyAnimatorRT.java
InputDevice.java                         ViewRootImpl.java
InputEvent.aidl                          ViewStructure.java
InputEventConsistencyVerifier.java       ViewStub.java
InputEvent.java                          ViewTreeObserver.java
InputEventReceiver.java                  WindowAnimationFrameStats.aidl
InputEventSender.java                    WindowAnimationFrameStats.java
InputFilter.java                         WindowCallbackWrapper.java
inputmethod                              WindowContentFrameStats.aidl
InputQueue.java                          WindowContentFrameStats.java
IOnKeyguardExitResult.aidl               WindowId.java
IRotationWatcher.aidl                    WindowInfo.aidl
IWindow.aidl                             WindowInfo.java
IWindowFocusObserver.aidl                WindowInsets.java
IWindowId.aidl                           Window.java
IWindowManager.aidl                      WindowManager.aidl
IWindowSession.aidl                      WindowManagerGlobal.java
IWindowSessionCallback.aidl              WindowManagerImpl.java
KeyCharacterMap.java                     WindowManagerInternal.java
KeyEvent.aidl                            WindowManager.java
KeyEvent.java                            WindowManagerPolicy.java
LayoutInflater.java


2. Activity顯示

2.1 Activity創(chuàng)建

/base/core/java/android/app/ActivityThread.java

handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
...............
    //根據(jù)類名以Java反射的方法創(chuàng)建一個Activity 
    Activity a = performLaunchActivity(r, customIntent);
    
    handleResumeActivity(r.token, false, r.isForward,
                    !r.activity.mFinished && !r.startsNotResumed);
................}

2.2 handleResumeActivity 

final void handleResumeActivity(IBinder token,
            boolean clearHide, boolean isForward, boolean reallyResume) {
.....................
if (r.window == null && !a.mFinished && willBeVisible) {
                r.window = r.activity.getWindow();
                //得到一個view對象
                View decor = r.window.getDecorView();
                decor.setVisibility(View.INVISIBLE);
                //獲得viewManager
                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;
                    //將view加入viewmanager
                    wm.addView(decor, l);
                }
}
..................................}

2.3 Activity 通過setContentView設(shè)置UI

Activity.java

public void setContentView(View view, ViewGroup.LayoutParams params) {
        getWindow().setContentView(view, params);
        initWindowDecorActionBar();
    }
    
 public Window getWindow() {
        return mWindow;
    }

上面出現(xiàn)了兩個和UI有關(guān)系的類:View和Window

Android Surface理解

2.4 Activity Window 與WindowManager
Activity.java

 final void attach(Context context, ActivityThread aThread,
            Instrumentation instr, IBinder token, int ident,
            Application application, Intent intent, ActivityInfo info,
            CharSequence title, Activity parent, String id,
            NonConfigurationInstances lastNonConfigurationInstances,
            Configuration config, String referrer, IVoiceInteractor voiceInteractor) {
        //創(chuàng)建window對象    
        mWindow = new PhoneWindow(this);
        mWindow.setCallback(this);
        mWindow.setOnWindowDismissedCallback(this);
        mWindow.getLayoutInflater().setPrivateFactory(this);
        //創(chuàng)建windowManager      
        mWindow.setWindowManager(
                (WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
                mToken, mComponent.flattenToString(),
                (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
         //保存WindowManager對象       
         mWindowManager = mWindow.getWindowManager();


 setWindowManager由PhoneWindow父類window.java實現(xiàn)

Window.java

public void setWindowManager(WindowManager wm, IBinder appToken, String appName,){
 mWindowManager = ((WindowManagerImpl)wm).createLocalWindowManager(this);
    }

WindowManagerImpl.java

public WindowManagerImpl createLocalWindowManager(Window parentWindow) {
        return new WindowManagerImpl(mDisplay, parentWindow);
    }
public final class WindowManagerImpl implements WindowManager {}

Android Surface理解

   (2.4)中流程總結(jié)

2.5 繼續(xù)分析setContentView()

Activity.java

public void setContentView(View view, ViewGroup.LayoutParams params) {
        getWindow().setContentView(view, params);
        initWindowDecorActionBar();
    }

PhoneWindow.java

 private ViewGroup mContentParent;
 public void setContentView(View view) {
        setContentView(view, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
    }
    
  public void setContentView(View view, ViewGroup.LayoutParams params) {
  //mContentParent是一個viewGroup對象
  if (mContentParent == null) {
            installDecor();
        } 
        
  if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
            view.setLayoutParams(params);
            final Scene newScene = new Scene(mContentParent, view);
            transitionTo(newScene);
        } else {
            //把view加入到ViewGroup中
            mContentParent.addView(view, params);
        }
  ........}

mContentParent是一個ViewGroup類型,它從View中派生,所以也是一個UI單元。從它名字中“Group”所表達(dá)的意思分析,它還可以包含其他的View元素。這又是什么意思呢?也就是說,在繪制一個ViewGroup時,它不僅需要把自己的樣子畫出來,還需要把它包含的View元素的樣子也畫出來。讀者可將它想象成一個容器,容器中的元素就是View。
installDecor()函數(shù)
主要用來給view繪制icon ,window title,logo, menu等等


2.6 重回handleResumeActivity 

我們之所以分析2.5內(nèi)容,是為了弄清楚View, ViewManager(就是WindowManager)這些對象

final void handleResumeActivity(IBinder token,
            boolean clearHide, boolean isForward, boolean reallyResume) {
.....................
if (r.window == null && !a.mFinished && willBeVisible) {
                r.window = r.activity.getWindow();
                //得到一個view對象
                View decor = r.window.getDecorView();
                decor.setVisibility(View.INVISIBLE);
                //獲得viewManager
                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;
                    //將view加入viewmanager
                    wm.addView(decor, l);
                }
}
..................................}

分析wm.addView(decor,l)

WindowManagerImpl.java

public final class WindowManagerImpl implements WindowManager {
    private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();
 public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
        applyDefaultToken(params);
        mGlobal.addView(view, params, mDisplay, mParentWindow);
    }

WindowManagerGlobal里面可以通過AIDL與IWindowManager.Stub.asInterface 及IWindowSessionCallback.Stub() IPC通信

WindowManagerGlobal.java

public void addView(View view, ViewGroup.LayoutParams params,
            Display display, Window parentWindow) {
            root = new ViewRootImpl(view.getContext(), display);
            view.setLayoutParams(wparams);
            mViews.add(view);
            mRoots.add(root);
            mParams.add(wparams);
            
            root.setView(view, wparams, panelParentView);// TAG 1


2.6.1 ViewRootImpl又是什么東東?


ViewRootImpl.java

public final class ViewRootImpl implements ViewParent,
        View.AttachInfo.Callbacks, HardwareRenderer.HardwareDrawCallbacks{
        final IWindowSession mWindowSession;
        final Display mDisplay;
        final DisplayManager mDisplayManager;
        final W mWindow;
        final Surface mSurface = new Surface();
        
        static class W extends IWindow.Stub {
        private final WeakReference<ViewRootImpl> mViewAncestor;
        private final IWindowSession mWindowSession;}


ViewRootImpl繼承了Handler類,看來它能處理消息。ViewRootImpl果真重寫了handleMessage函數(shù)

一個成員變量叫mSurface,它是Surface類型

surface.java
public class Surface implements Parcelable {

一個W類型的mWindow和一個View類型的mView變量

ViewRootImpl有一個成員變量mSurface,它是Surface類型,它和一塊Raw Buffer有關(guān)聯(lián)。

ViewRootImpl是一個ViewParent,它的子View的繪畫操作,是在畫布Surface上展開的

ViewRootImpl的構(gòu)造

public ViewRootImpl(Context context, Display display) {
    mDisplay = display;//Display.java Provides information about the size and density of a logical display.
    mWindowSession = WindowManagerGlobal.getWindowSession(); // IWindowSession AIDLmWindo    w = new W(this); //內(nèi)部W對象,實際是與window通信的AIDL static class W extends IWindow.Stub
    mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);

WindowManagerGlobal.getWindowSession()將建立Activity的ViewRoot和WindowManagerService的關(guān)系

WindowManagerGlobal.java

 public static IWindowSession getWindowSession() {
 
     IWindowManager windowManager = getWindowManagerService();//得到Iwindowmanager對象,
     //IWindowManager 的AIDL Bn端是WindowManagerService class WindowManagerService extends IWindowManager.Stub
     sWindowSession = windowManager.openSession( //然后通過AIDL得到windowsession aidl 對象 不清楚為啥已經(jīng)有了windowmanager的aidl 干嘛還需要windowsession aidl
     new IWindowSessionCallback.Stub() { })
 }  
 public static IWindowManager getWindowManagerService() {
     sWindowManagerService = IWindowManager.Stub.asInterface(
               ServiceManager.getService("window")); //得到WindowManager AIDL BP對象
         try {
                  sWindowManagerService = getWindowManagerService();
                  ValueAnimator.setDurationScale(sWindowManagerService.getCurrentAnimatorScale());                
              } catch (RemoteException e) {}

ViewRootImpl和WMS的關(guān)系

/frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java

public class WindowManagerService extends IWindowManager.Stub
        implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs {}
        
        public IWindowSession openSession(IWindowSessionCallback callback, IInputMethodClient client,
            IInputContext inputContext) {
        Session session = new Session(this, callback, client, inputContext);
        return session;
    }

/frameworks/base/services/core/java/com/android/server/wm/Session.java

    final class Session extends IWindowSession.Stub
        implements IBinder.DeathRecipient {
        final WindowManagerService mService;
        final IWindowSessionCallback mCallback;
        final IInputMethodClient mClient;


分析完ViewRootImpl創(chuàng)建過程后,現(xiàn)在返回TAG 1處繼續(xù)分析ViewRootImpl.setView()
2.6.2 ViewRootImpl.setView()

/frameworks/base/core/java/android/view/ViewRootImpl.java

public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {

    // Compute surface insets required to draw at specified Z value.
    // TODO: Use real shadow insets for a constant max Z.
           if (!attrs.hasManualSurfaceInsets) {
                final int surfaceInset = (int) Math.ceil(view.getZ() * 2);
                attrs.surfaceInsets.set(surfaceInset, surfaceInset, surfaceInset, surfaceInset);} //計算Z軸坐標(biāo)
                
    requestLayout();
    res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
              getHostVisibility(), mDisplay.getDisplayId(),
              mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
              mAttachInfo.mOutsets, mInputChannel);
//requestLayout()流程  TAG2

public void requestLayout() {        scheduleTraversals();}

void scheduleTraversals() {
        mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
        mChoreographer.postCallback(
             Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
        notifyRendererOfFramePending();
        pokeDrawLockIfNeeded();}
        
final TraversalRunnable mTraversalRunnable = new TraversalRunnable();
//Runnable實現(xiàn)多線程,避免點繼承的局限,一個類可以繼承多個接口.適合于資源的共享
final class TraversalRunnable implements Runnable {
        @Override
        public void run() {
            doTraversal();
        }
    }
    
void doTraversal() {
    performTraversals();}

private void performTraversals() {
     //mSurface是 surface.java 對象, final Surface mSurface = new Surface();
    // surface.java 通過jni 可以操作Surface.cpp 中surface對象 Surface::Surface(
    //    const sp<IGraphicBufferProducer>& bufferProducer,
    //    bool controlledByApp)
    if (mSurface.isValid()) { 
        if (mAttachInfo.mHardwareRenderer != null) {
            try {
                hwInitialized = mAttachInfo.mHardwareRenderer.initialize(mSurface);
                if (hwInitialized && (host.mPrivateFlags
                     & View.PFLAG_REQUEST_TRANSPARENT_REGIONS) == 0) {
                    // Don't pre-allocate if transparent regions
                    // are requested as they may not be needed
                       mSurface.allocateBuffers();
                }
        }
     //Interface for rendering a view hierarchy using hardware acceleration.
     final HardwareRenderer hardwareRenderer = mAttachInfo.mHardwareRenderer;
     hardwareRenderer.setup(mWidth, mHeight, mAttachInfo,
                            mWindowAttributes.surfaceInsets); 
}
mWindowSession.addToDisplay流程

//mWindowSession(IWindowSession) 通過AIDL 與Session.java交互 final class Session extends IWindowSession.Stub
public int addToDisplay(IWindow window, int seq, WindowManager.LayoutParams attrs,
            int viewVisibility, int displayId, Rect outContentInsets, Rect outStableInset    s,Rect outOutsets, InputChannel outInputChannel) {
        return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId,
                outContentInsets, outStableInsets, outOutsets, outInputChannel);
    }
final WindowManagerService mService;
WindowManagerService.java
public int addWindow(Session session, IWindow client, int seq,
       WindowManager.LayoutParams attrs, int viewVisibility, int displayId,
       Rect outContentInsets, Rect outStableInsets, Rect outOutsets,
       InputChannel outInputChannel) {
            //windowstate A window in the window manager.class WindowState implements WindowManagerPolicy.WindowState 
            WindowState win = new WindowState(this, session, client, token,
                attachedWindow, appOp[0], seq, attrs, viewVisibility, displayContent);
            win.attach();
}
WindowState.java
void attach() {
        mSession.windowAddedLocked();}
Session.java
void windowAddedLocked() {   
    mSurfaceSession = new SurfaceSession();
    mService.mSessions.add(this);
    mNumWindow++;
}

ViewRootImpl 與WMS關(guān)系總結(jié)

Android Surface理解ViewRootImpl通過IWindowSession和WMS進(jìn)程進(jìn)行跨進(jìn)程通信。
ViewRootImpl內(nèi)部有一個W類型的對象,它也是一個基于Binder通信的類,W是IWindow的Bn端,用于響應(yīng)請求。IWindow定義在另一個aidl文件IWindow.aidl中
IWindowSession

System private per-application interface to the window manager.

IWindow 

API back to a client window that the Window Manager uses to inform it of interesting things happening.


IWindow.aidl
void dispatchAppVisibility(boolean visible);
void dispatchWallpaperCommand(

void dispatchDragEvent(in DragEvent event);
void dispatchWindowShown();

這里的事件指的就是按鍵、觸屏等事件。那么,一個按鍵事件是如何被分發(fā)的呢?下面是它大致的流程:WMS所在的SystemServer進(jìn)程接收到按鍵事件。WMS找到UI位于屏幕頂端的進(jìn)程所對應(yīng)的IWindow對象,調(diào)用這個IWindow對象的dispatchKey。IWindow對象的Bn端位于ViewRoot中,ViewRoot再根據(jù)內(nèi)部View的位置信息找到真正處理這個事件的View,最后調(diào)用dispatchKey函數(shù)完成按鍵的處理。(這段過程沒有去跟代碼)

2.7 Activity的UI繪制

    在TAG2處分析過requestLayout。根據(jù)前面的分析可知,最終調(diào)用到performTraversals()

ViewRootImpl.java

private void performTraversals() {
    relayoutResult = relayoutWindow(params, viewVisibility, insetsPending);//TAG3
    performDraw();//開始繪制
    }
     
private int relayoutWindow(WindowManager.LayoutParams params, int viewVisibility,
    boolean insetsPending) throws RemoteException {
        int relayoutResult = mWindowSession.relayout(
                mWindow, mSeq, params,
                (int) (mView.getMeasuredWidth() * appScale + 0.5f),
                (int) (mView.getMeasuredHeight() * appScale + 0.5f),
                viewVisibility, insetsPending ? WindowManagerGlobal.RELAYOUT_INSETS_PENDING : 0,
                mWinFrame, mPendingOverscanInsets, mPendingContentInsets, mPendingVisibleInsets,
                mPendingStableInsets, mPendingOutsets, mPendingConfiguration, mSurface);
    }//這個函數(shù)通過AIDL調(diào)用到WMS relayoutWindow().暫時不繼續(xù)分析
    
private void performDraw() {
     draw(fullRedrawNeeded);}
     
private void draw(boolean fullRedrawNeeded){
     mAttachInfo.mHardwareRenderer.draw(mView, mAttachInfo, this);//hw render完成draw
     //HardwareRenderer.java abstract void draw() }

2.8 Activity 總結(jié)

    Activity的頂層View是DecorView,而我們在onCreate函數(shù)中通過setContentView設(shè)置的View只不過是這個DecorView中的一部分罷了。DecorView是一個FrameLayout類型的ViewGroup。
     Activity和UI有關(guān),它包含一個Window(真實類型是PhoneWindow)和一個WindowManager(真實類型是LocalWindowManager)對象。這兩個對象將控制整個Activity的顯示。
    LocalWindowManager使用了WindowManagerImpl做為最終的處理對象(Proxy模式),這個WindowManagerImpl中有一個ViewRootImpl對象。ViewRootImpl實現(xiàn)了ViewParent接口,它有兩個重要的成員變量,一個是mView,它指向Activity頂層UI單元的DecorView,另外有一個mSurface,這個Surface包含了一個Canvas(畫布)(這個surface java對象可以通過JNI 與 surface.cpp中對象交互)。除此之外,ViewRooImplt還通過Binder系統(tǒng)和WindowManagerService進(jìn)行了跨進(jìn)程交互。
     ViewRoot能處理Handler的消息,Activity的顯示就是由ViewRoot在它的performTraversals函數(shù)中完成的。

3. Surface對象

    終于可以分析java與C++處surface對象了,先回憶下surface是如何創(chuàng)建的

    ViewRootImpl.java
    final Surface mSurface = new Surface();

     ViewRootImpl通過IWindowSession和WMS交互,而WMS中會調(diào)用的一個attach函數(shù),會構(gòu)造一個SurfaceSession,前面遇到過但沒有繼續(xù)分析

WindowState.java
void attach() {
        mSession.windowAddedLocked();}
Session.java
void windowAddedLocked() {   
    mSurfaceSession = new SurfaceSession();
    mService.mSessions.add(this);
    mNumWindow++;
}
SurfaceSession.java
 //* An instance of this class represents a connection to the surface
 //* flinger, from which you can create one or more Surface instances that will
 //* be composited to the screen.
public final class SurfaceSession {
    private static native long nativeCreate();
    private static native void nativeDestroy(long ptr);
    private static native void nativeKill(long ptr);}

 由注釋可見,surfacesession負(fù)責(zé)與SF的連接

  在2.7處Activity UI 繪制時,遇到過relayoutWindow(),現(xiàn)在繼續(xù)看該函數(shù)

   ViewRootImpl.java

private void performTraversals() {
    relayoutResult = relayoutWindow(params, viewVisibility, insetsPending);//TAG3
    performDraw();//開始繪制
    }
     
private int relayoutWindow(WindowManager.LayoutParams params, int viewVisibility,
    boolean insetsPending) throws RemoteException {
        int relayoutResult = mWindowSession.relayout(
                mWindow, mSeq, params,
                (int) (mView.getMeasuredWidth() * appScale + 0.5f),
                (int) (mView.getMeasuredHeight() * appScale + 0.5f),
                viewVisibility, insetsPending ? WindowManagerGlobal.RELAYOUT_INSETS_PENDING : 0,
                mWinFrame, mPendingOverscanInsets, mPendingContentInsets, mPendingVisibleInsets,
                mPendingStableInsets, mPendingOutsets, mPendingConfiguration, mSurface);
    }//這個函數(shù)通過AIDL調(diào)用到WMS relayoutWindow()
Session.java
public int relayout(IWindow window, int seq, WindowManager.LayoutParams attrs,..){
    int res = mService.relayoutWindow(this,....);}
WindowManagerService.java
public int relayoutWindow(Session session, IWindow client, int seq,
            WindowManager.LayoutParams attrs, int requestedWidth,....){
    SurfaceControl surfaceControl = winAnimator.createSurfaceLocked();//TAG4 創(chuàng)建本地surfacecontrol 通過JNI會調(diào)用C++最終創(chuàng)建layer, java層保存的surfacecontrol對象是一個surfaceControl.cpp 中對象
    //JNI處返回的surfacecontrol
    //surface->incStrong((void *)nativeCreate);
    //return reinterpret_cast<jlong>(surface.get()); 
   
    outSurface.copyFrom(surfaceControl);//將本地surface拷貝到outSurface }
WindowStateAnimator.java
SurfaceControl createSurfaceLocked() {
    final WindowState w = mWin;
    mSurfaceControl = new SurfaceControl(
               mSession.mSurfaceSession,
               attrs.getTitle().toString(),
               width, height, format, flags);
   // Start a new transaction and apply position & offset.
   SurfaceControl.openTransaction();
   mSurfaceControl.setLayer(mAnimLayer);
   mSurfaceControl.setAlpha(0);
   SurfaceControl.closeTransaction();
   return mSurfaceControl;
}

SurfaceControl是個什么對象?與Surface有何關(guān)系
/frameworks/base/core/java/android/view/SurfaceControl.java
看SurfaceControl構(gòu)造函數(shù)說明,surfacecontrol根據(jù)name創(chuàng)建surface

/**
* Create a surface with a name.
* <p>
* The surface creation flags specify what kind of surface to create and
* certain options such as whether the surface can be assumed to be opaque
* and whether it should be initially hidden.  Surfaces should always be
* created with the {@link #HIDDEN} flag set to ensure that they are not
* made visible prematurely before all of the surface's properties have been
* configured.
* <p>
* Good practice is to first create the surface with the {@link #HIDDEN} flag
* specified, open a transaction, set the surface layer, layer stack, alpha,
* and position, call {@link #show} if appropriate, and close the transaction.
*
* @param session The surface session, must not be null.
* @param name The surface name, must not be null.
* @param w The surface initial width.
* @param h The surface initial height.
* @param flags The surface creation flags.  Should always include {@link #HIDDEN}
* in the creation flags.
*
* @throws throws OutOfResourcesException If the SurfaceControl cannot be created.
*/
public SurfaceControl(SurfaceSession session,
            String name, int w, int h, int format, int flags){
       mNativeObject = nativeCreate(session, name, w, h, format, flags);
 }
通過JNI android_view_SurfaceControl.cpp
static jlong nativeCreate(JNIEnv* env, jclass clazz, jobject sessionObj,
        jstring nameStr, jint w, jint h, jint format, jint flags) {
    ScopedUtfChars name(env, nameStr);
    sp<SurfaceComposerClient> client(android_view_SurfaceSession_getClient(env, sessionObj));
    sp<SurfaceControl> surface = client->createSurface(
            String8(name.c_str()), w, h, format, flags); }
調(diào)用SurfaceComposiClient.cpp
sp<SurfaceControl> SurfaceComposerClient::createSurface(
        const String8& name,
        uint32_t w,
        uint32_t h,
        PixelFormat format,
        uint32_t flags){
        sp<SurfaceControl> sur;
        sp<IGraphicBufferProducer> gbp;
        status_t err = mClient->createSurface(name, w, h, format, flags,
                &handle, &gbp);//mClient 是一個sp<ISurfaceComposerClient>對象,由class Client : public BnSurfaceComposerClient來接收IPC交互,
        sur = new SurfaceControl(this, handle, gbp);// 最終通過JNI返回到TAG4處
        return sur;
}
Client.cpp
// ISurfaceComposerClient interface
/* Client是用來與surfaceflinger交互的橋梁,在sf中被創(chuàng)建 
sp<ISurfaceComposerClient> SurfaceFlinger::createConnection()
{
    sp<ISurfaceComposerClient> bclient;
    sp<Client> client(new Client(this));
*/
status_t Client::createSurface(
        const String8& name,
        uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
        sp<IBinder>* handle,
        sp<IGraphicBufferProducer>* gbp){
        result = flinger->createLayer(name, client, w, h, format, flags,
                    handle, gbp);}//這里面的flinger是由Client::Client(const sp<SurfaceFlinger>& flinger)在創(chuàng)建時保存起來的
    : mFlinger(flinger)
}
Surfaceflinger.cpp
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){
        sp<Layer> layer;

        switch (flags & ISurfaceComposerClient::eFXSurfaceMask) {
        case ISurfaceComposerClient::eFXSurfaceNormal:
            result = createNormalLayer(client,//創(chuàng)建普通layer gbp是在layer中進(jìn)行賦值
                    name, w, h, flags, format,
                    handle, gbp, &layer);
            break;
        case ISurfaceComposerClient::eFXSurfaceDim:
            result = createDimLayer(client,//創(chuàng)建磨砂l(fā)ayer gbp是在layer中進(jìn)行賦值
                    name, w, h, flags,
                    handle, gbp, &layer);
            break;
        default:
            result = BAD_VALUE;
            break;
            
        result = addClientLayer(client, *handle, *gbp, layer);//attach this layer to the client
    }
 //Client中createSurface函數(shù),調(diào)用的是SF中createLayer
 //與前面ViewrootImpl.java中 final Surface mSurface = new Surface();有何區(qū)分?Layer與surface是如何區(qū)分?  前面遇到j(luò)ava surface用于drawSoftware或hwRender時 ex drawsoftware() canvas = mSurface.lockCanvas(dirty);mView.draw(canvas);

Android Surface理解上述流程的小結(jié)

3.1 Surface與畫圖

  lockCanvas 

 Surface.java
 * Gets a {@link Canvas} for drawing into this surface.
        public Canvas lockCanvas(Rect inOutDirty){
            mLockedObject = nativeLockCanvas(mNativeObject, mCanvas, inOutDirty);
            return mCanvas;
        }

   調(diào)用JNI
   android_view_Surface.cpp

static jlong nativeLockCanvas(JNIEnv* env, jclass clazz,
        jlong nativeObject, jobject canvasObj, jobject dirtyRectObj) {
    sp<Surface> surface(reinterpret_cast<Surface *>(nativeObject));
    
    Rect dirtyRect;
    Rect* dirtyRectPtr = NULL;

    if (dirtyRectObj) {
        dirtyRect.left   = env->GetIntField(dirtyRectObj, gRectClassInfo.left);
        dirtyRect.top    = env->GetIntField(dirtyRectObj, gRectClassInfo.top);
        dirtyRect.right  = env->GetIntField(dirtyRectObj, gRectClassInfo.right);
        dirtyRect.bottom = env->GetIntField(dirtyRectObj, gRectClassInfo.bottom);
        dirtyRectPtr = &dirtyRect;
    }
    
    ANativeWindow_Buffer outBuffer;
    status_t err = surface->lock(&outBuffer, dirtyRectPtr);//一塊表示臟區(qū)域的dirtyRectPtr
    //從surface.cpp 中dequeueBuffer()獲得一個GraphicBuffer, 然后將buffer的長寬,format 等賦制給outBuffer,
    
    //
    SkImageInfo info = SkImageInfo::Make(outBuffer.width, outBuffer.height,
                                         convertPixelFormat(outBuffer.format),
                                         kPremul_SkAlphaType);
                                         
    SkBitmap bitmap;
    ssize_t bpr = outBuffer.stride * bytesPerPixel(outBuffer.format);
    bitmap.setInfo(info, bpr);
    
     if (outBuffer.width > 0 && outBuffer.height > 0) {
        bitmap.setPixels(outBuffer.bits); // bitmap 指向一片存儲區(qū)域
    } else {
        // be safe with an empty bitmap.
        bitmap.setPixels(NULL);
    }
    
    Canvas* nativeCanvas = GraphicsJNI::getNativeCanvas(env, canvasObj);
    nativeCanvas->setBitmap(bitmap);//將Bitmap設(shè)置到這個Canvas中,這樣進(jìn)UI繪畫時就有畫布了
    // Create another reference to the surface and return it.  This reference
    // should be passed to nativeUnlockCanvasAndPost in place of mNativeObject,
    // because the latter could be replaced while the surface is locked.
    sp<Surface> lockedSurface(surface);
    lockedSurface->incStrong(&sRefBaseOwner);
    return (jlong) lockedSurface.get();
 }

   lockCanvas獲得一塊存儲區(qū)域,然后將它和Canvas綁定到一起,這樣,UI繪畫的結(jié)果就記錄在這塊存儲區(qū)域里了

  再看unlockCanvas
 Surface.java

  private void unlockSwCanvasAndPost(Canvas canvas) { // 只有sw 渲染的才走這邊?
      try {
            nativeUnlockCanvasAndPost(mLockedObject, canvas);
          } finally {
            nativeRelease(mLockedObject);
            mLockedObject = 0;
        }
  }

android_view_Surface.cpp

static void nativeUnlockCanvasAndPost(JNIEnv* env, jclass clazz,
        jlong nativeObject, jobject canvasObj) {
            sp<Surface> surface(reinterpret_cast<Surface *>(nativeObject));        
// detach the canvas from the surface
    Canvas* nativeCanvas = GraphicsJNI::getNativeCanvas(env, canvasObj);
    nativeCanvas->setBitmap(SkBitmap());
    // unlock surface
    status_t err = surface->unlockAndPost();
}

Surface.cpp

status_t Surface::unlockAndPost()
{
    status_t err = mLockedBuffer->unlockAsync(&fd);
    //通過mGraphicBufferProducer->queueBuffer
    err = queueBuffer(mLockedBuffer.get(), fd);
}

直接使用別人的圖片surface畫圖過程

Android Surface理解


    

    回憶下上文surface 是如何創(chuàng)建的

sp<SurfaceControl> SurfaceComposerClient::createSurface(
        const String8& name,
        uint32_t w,
        uint32_t h,
        PixelFormat format,
        uint32_t flags){
        sp<IGraphicBufferProducer> gbp;
        status_t err = mClient->createSurface(name, w, h, format, flags,
                &handle, &gbp);
        ALOGE_IF(err, "SurfaceComposerClient::createSurface error %s", strerror(-err));
        if (err == NO_ERROR) {
            sur = new SurfaceControl(this, handle, gbp);
        }
}

 

mClient  sp<ISurfaceComposerClient>  mClient;

  class Client : public BnSurfaceComposerClient

  Client 中mFlinger  sp<SurfaceFlinger> mFlinger;  這樣SurfaceComposerClient 就通過IPC 與surfaceflinger 交互起來了

status_t Client::createSurface(
        const String8& name,
        uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
        sp<IBinder>* handle,
        sp<IGraphicBufferProducer>* gbp)
{    
    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();
}



Client::createSurface() 與 android_view_Surface.cpp 中nativeReadFromParcel

surfacecontrol.cpp
status_t SurfaceControl::writeSurfaceToParcel(
        const sp<SurfaceControl>& control, Parcel* parcel)
{
    sp<IGraphicBufferProducer> bp;
    if (control != NULL) {
        bp = control->mGraphicBufferProducer;
    }
    return parcel->writeStrongBinder(IInterface::asBinder(bp));//Surface 核心是不是就是IGraphicBufferProducer 指針
}
android_view_Surface.cpp
static jlong nativeReadFromParcel(JNIEnv* env, jclass clazz,
        jlong nativeObject, jobject parcelObj) {
    Parcel* parcel = parcelForJavaObject(env, parcelObj);
sp<Surface> self(reinterpret_cast<Surface *>(nativeObject));
    sp<IBinder> binder(parcel->readStrongBinder());
    // update the Surface only if the underlying IGraphicBufferProducer
    // has changed.
    if (self != NULL
            && (IInterface::asBinder(self->getIGraphicBufferProducer()) == binder)) {
        // same IGraphicBufferProducer, return ourselves
        return jlong(self.get());// 直接返回surface sp
    }
    //當(dāng)GraphicBufferProducer改變時,新建一個surface,并將原先surface decStrong 釋放,返回新surface指針
    sp<Surface> sur;
    sp<IGraphicBufferProducer> gbp(interface_cast<IGraphicBufferProducer>(binder));
    if (gbp != NULL) {
        // we have a new IGraphicBufferProducer, create a new Surface for it
        sur = new Surface(gbp, true);
        // and keep a reference before passing to java
        sur->incStrong(&sRefBaseOwner);
    }
    if (self != NULL) {
        // and loose the java reference to ourselves
        self->decStrong(&sRefBaseOwner);
    }
    return jlong(sur.get());


向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI