您好,登錄后才能下訂單哦!
結合別人的博客和自己看的代碼,梳理下自己對surface的理解
1.代碼相關文件
/AOSP/frameworks/native/libs/ui
主要是bufferqueuecore與surfaceflinger中分配
GraphicBufferAllocator 通過hw_get_module()&gralloc_open與硬件提供的設備交互
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及layer
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創建
/base/core/java/android/app/ActivityThread.java
handleLaunchActivity(ActivityClientRecord r, Intent customIntent) { ............... //根據類名以Java反射的方法創建一個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設置UI
Activity.java
public void setContentView(View view, ViewGroup.LayoutParams params) { getWindow().setContentView(view, params); initWindowDecorActionBar(); } public Window getWindow() { return mWindow; }
上面出現了兩個和UI有關系的類:View和Window
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) { //創建window對象 mWindow = new PhoneWindow(this); mWindow.setCallback(this); mWindow.setOnWindowDismissedCallback(this); mWindow.getLayoutInflater().setPrivateFactory(this); //創建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實現
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 {}
(2.4)中流程總結
2.5 繼續分析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”所表達的意思分析,它還可以包含其他的View元素。這又是什么意思呢?也就是說,在繪制一個ViewGroup時,它不僅需要把自己的樣子畫出來,還需要把它包含的View元素的樣子也畫出來。讀者可將它想象成一個容器,容器中的元素就是View。
installDecor()函數
主要用來給view繪制icon ,window title,logo, menu等等
2.6 重回handleResumeActivity
我們之所以分析2.5內容,是為了弄清楚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函數
一個成員變量叫mSurface,它是Surface類型
surface.java public class Surface implements Parcelable {
一個W類型的mWindow和一個View類型的mView變量
ViewRootImpl有一個成員變量mSurface,它是Surface類型,它和一塊Raw Buffer有關聯。
ViewRootImpl是一個ViewParent,它的子View的繪畫操作,是在畫布Surface上展開的
ViewRootImpl的構造
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); //內部W對象,實際是與window通信的AIDL static class W extends IWindow.Stub mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
WindowManagerGlobal.getWindowSession()將建立Activity的ViewRoot和WindowManagerService的關系
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 對象 不清楚為啥已經有了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) {}
/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創建過程后,現在返回TAG 1處繼續分析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軸坐標 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實現多線程,避免點繼承的局限,一個類可以繼承多個接口.適合于資源的共享 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關系總結
ViewRootImpl通過IWindowSession和WMS進程進行跨進程通信。
ViewRootImpl內部有一個W類型的對象,它也是一個基于Binder通信的類,W是IWindow的Bn端,用于響應請求。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();
這里的事件指的就是按鍵、觸屏等事件。那么,一個按鍵事件是如何被分發的呢?下面是它大致的流程:WMS所在的SystemServer進程接收到按鍵事件。WMS找到UI位于屏幕頂端的進程所對應的IWindow對象,調用這個IWindow對象的dispatchKey。IWindow對象的Bn端位于ViewRoot中,ViewRoot再根據內部View的位置信息找到真正處理這個事件的View,最后調用dispatchKey函數完成按鍵的處理。(這段過程沒有去跟代碼)
2.7 Activity的UI繪制
在TAG2處分析過requestLayout。根據前面的分析可知,最終調用到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); }//這個函數通過AIDL調用到WMS relayoutWindow().暫時不繼續分析 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 總結
Activity的頂層View是DecorView,而我們在onCreate函數中通過setContentView設置的View只不過是這個DecorView中的一部分罷了。DecorView是一個FrameLayout類型的ViewGroup。
Activity和UI有關,它包含一個Window(真實類型是PhoneWindow)和一個WindowManager(真實類型是LocalWindowManager)對象。這兩個對象將控制整個Activity的顯示。
LocalWindowManager使用了WindowManagerImpl做為最終的處理對象(Proxy模式),這個WindowManagerImpl中有一個ViewRootImpl對象。ViewRootImpl實現了ViewParent接口,它有兩個重要的成員變量,一個是mView,它指向Activity頂層UI單元的DecorView,另外有一個mSurface,這個Surface包含了一個Canvas(畫布)(這個surface java對象可以通過JNI 與 surface.cpp中對象交互)。除此之外,ViewRooImplt還通過Binder系統和WindowManagerService進行了跨進程交互。
ViewRoot能處理Handler的消息,Activity的顯示就是由ViewRoot在它的performTraversals函數中完成的。
3. Surface對象
終于可以分析java與C++處surface對象了,先回憶下surface是如何創建的
ViewRootImpl.java final Surface mSurface = new Surface();
ViewRootImpl通過IWindowSession和WMS交互,而WMS中會調用的一個attach函數,會構造一個SurfaceSession,前面遇到過但沒有繼續分析
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負責與SF的連接
在2.7處Activity UI 繪制時,遇到過relayoutWindow(),現在繼續看該函數
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); }//這個函數通過AIDL調用到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 創建本地surfacecontrol 通過JNI會調用C++最終創建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有何關系
/frameworks/base/core/java/android/view/SurfaceControl.java
看SurfaceControl構造函數說明,surfacecontrol根據name創建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); } 調用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中被創建 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)在創建時保存起來的 : 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,//創建普通layer gbp是在layer中進行賦值 name, w, h, flags, format, handle, gbp, &layer); break; case ISurfaceComposerClient::eFXSurfaceDim: result = createDimLayer(client,//創建磨砂layer gbp是在layer中進行賦值 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函數,調用的是SF中createLayer //與前面ViewrootImpl.java中 final Surface mSurface = new Surface();有何區分?Layer與surface是如何區分? 前面遇到java surface用于drawSoftware或hwRender時 ex drawsoftware() canvas = mSurface.lockCanvas(dirty);mView.draw(canvas);
上述流程的小結
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; }
調用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);//一塊表示臟區域的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 指向一片存儲區域 } else { // be safe with an empty bitmap. bitmap.setPixels(NULL); } Canvas* nativeCanvas = GraphicsJNI::getNativeCanvas(env, canvasObj); nativeCanvas->setBitmap(bitmap);//將Bitmap設置到這個Canvas中,這樣進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獲得一塊存儲區域,然后將它和Canvas綁定到一起,這樣,UI繪畫的結果就記錄在這塊存儲區域里了
再看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畫圖過程
回憶下上文surface 是如何創建的
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 } //當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());
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。