Surface的管理

Surface是窗口能真正显示到物理屏幕上的基础,由surfaceflinger管理,可以通过WindowStateAnimator.java中的变量mDrawState来查看每个窗口相关的surface的状态。

surface有5中状态:

WindowStateAnimator.java

//Surface还没有创建。

staticfinal int NO_SURFACE = 0;

//Surface已经创建,但是窗口还没绘制,这时surface是隐藏的。

staticfinal int DRAW_PENDING = 1;

//窗口已经完成了第一次绘制,但是surface还没有显示,Surface将会在下次layout时显示出来。

staticfinal int COMMIT_DRAW_PENDING = 2;

//窗口的绘制请求已经提交,surface还没真正的显示,这通常用于延迟显示surface直到这个token中的所有窗口都已准备显示。

staticfinal int READY_TO_SHOW = 3;

//窗口已经第一次在屏幕上显示出来。

staticfinal int HAS_DRAWN = 4;

  1. String drawStateToString() @WindowStateAnimator.java{
  2. switch (mDrawState) {
  3. case NO_SURFACE: return "NO_SURFACE";
  4. case DRAW_PENDING: return "DRAW_PENDING";
  5. case COMMIT_DRAW_PENDING: return "COMMIT_DRAW_PENDING";
  6. case READY_TO_SHOW: return "READY_TO_SHOW";
  7. case HAS_DRAWN: return "HAS_DRAWN";
  8. default: return Integer.toString(mDrawState);
  9. }
  10. }
  11. int mDrawState;

1),Surface的申请

WMS只负责窗口的层级和属性,surfaceflinger负责真正的将数据合成并显示到屏幕上。UI数据的绘制需要有画板,就是BufferQueue的支持,不管是那类窗口都要向surfaceflinger申请相应的layer,进一步得到缓冲区的使用权。这一切的启动是在viewroot中执行viewtree遍历时,会想WMS申请一个surface。

具体是从relayoutWindow开始,重新布局窗口,应用进程通过mWindowSession.relayout让WMS向surfaceflinger申请画板,然后通过最后一个参数mSurface将结果返回。

  1. final Surface mSurface = new Surface();
  2. private int relayoutWindow(WindowManager.LayoutParams params, int viewVisibility,
  3. boolean insetsPending) throws RemoteException@ViewRootImpl.java {
  4. int relayoutResult = mWindowSession.relayout(
  5. mWindow, mSeq, params,
  6. (int) (mView.getMeasuredWidth() * appScale + 0.5f),
  7. (int) (mView.getMeasuredHeight() * appScale + 0.5f),
  8. viewVisibility, insetsPending ? WindowManagerGlobal.RELAYOUT_INSETS_PENDING : 0,
  9. mWinFrame, mPendingOverscanInsets, mPendingContentInsets, mPendingVisibleInsets,
  10. mPendingStableInsets, mPendingOutsets, mPendingBackDropFrame, mPendingConfiguration,
  11. mSurface);
  12. }

接着看surface是怎么申请的,先看IwindowSession中的处理。

  1. public int relayout(android.view.IWindow window, int seq, android.view.WindowManager.LayoutParams attrs, int requestedWidth, int requestedHeight, int viewVisibility, int flags, android.graphics.Rect outFrame, android.graphics.Rect outOverscanInsets, android.graphics.Rect outContentInsets, android.graphics.Rect outVisibleInsets, android.graphics.Rect outStableInsets, android.graphics.Rect outOutsets, android.graphics.Rect outBackdropFrame, android.content.res.Configuration outConfig, android.view.Surface outSurface) throws android.os.RemoteException
  2. @IwindowSession.java$IWindowSession$Stub$Proxy{
  3. //通过Binder向服务端发送请求TRANSACTION_relayout,
  4. mRemote.transact(Stub.TRANSACTION_relayout, _data, _reply, 0);
  5. //收到恢复后,从reply中取出结果,这是客户端的实现,具体取出的是什么,就要看服务端写入的什么了。
  6. outSurface.readFromParcel(_reply);
  7. }

//看服务端的处理。

  1. public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
  2. @IwindowSession.java$IWindowSession$Stub{
  3. switch (code){
  4. //跟客户端相同的业务码TRANSACTION_relayout
  5. case TRANSACTION_relayout:
  6. {
  7. //服务器端,首先创建了一个surface对象,然后调用WMS的relayoutWindow函数为这个对象赋值,最后通过_arg15.writeToParcel把结果写入回复的parcel中。如果一个类想在aidl机制中,客户度与服务端之间传递,就要继承Parcelable接口,并实现writeToParcel方法。
  8. android.view.Surface _arg15;
  9. _arg15 = new android.view.Surface();
  10. //这里会调用服务端Session.java中的实现,进一步调用WMS中的relayoutWindow。
  11. int _result = this.relayout(_arg0, _arg1, _arg2, _arg3, _arg4, _arg5, _arg6, _arg7, _arg8, _arg9, _arg10, _arg11,
  12. _arg12, _arg13, _arg14, _arg15);
  13. _arg15.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
  14. }
  15. }
  16. }
  1. public int relayoutWindow(Session session, IWindow client, int seq,
  2. WindowManager.LayoutParams attrs, int requestedWidth,
  3. int requestedHeight, int viewVisibility, int flags,
  4. Rect outFrame, Rect outOverscanInsets, Rect outContentInsets,
  5. Rect outVisibleInsets, Rect outStableInsets, Rect outOutsets, Rect outBackdropFrame,
  6. Configuration outConfig, Surface outSurface) @WindowManagerService.java{
  7. //每个windowState都有一个mWinAnimator来处理窗口的退出和进入动画。
  8. WindowStateAnimator winAnimator = win.mWinAnimator;
  9. //设置用户请求的宽、高,这值也会影响到surface的属性。
  10. win.setRequestedSize(requestedWidth, requestedHeight);
  11. //生成surface对象,通过outSurface.copyFrom返回客户端。
  12. result = createSurfaceControl(outSurface, result, win, winAnimator);
  13.  
  14. updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
  15. false /*updateInputWindows*/)
  16.  
  17. mWindowPlacerLocked.performSurfacePlacement();
  18. }

WMS并没有直接生成surface的操作,继续跟踪createSurfaceControl。

  1. private int createSurfaceControl(Surface outSurface, int result, WindowState win,
  2. WindowStateAnimator winAnimator) @WindowManagerService.java{
  3. // createSurfaceLocked将会生成一个真正的surface,并有SurfaceControl来管理。
  4. WindowSurfaceController surfaceController = winAnimator.createSurfaceLocked();
  5. if (surfaceController != null) {
  6. surfaceController.getSurface(outSurface);
  7. }
  8. }

//管理Surface的mSurfaceControl变量是在WindowSurfaceController的构造函数中生成的。

  1. WindowSurfaceController createSurfaceLocked() @WindowStateAnimator.java{
  2. mSurfaceController = new WindowSurfaceController(mSession.mSurfaceSession,
  3. attrs.getTitle().toString(),
  4. width, height, format, flags, this);
  5. }

接着看SurfaceControl的构造函数。

  1. long mNativeObject;
  2. public SurfaceControl(SurfaceSession session,
  3. String name, int w, int h, int format, int flags){
  4. //调用的nativeCreate函数,将会建立跟SurfaceFlinger的联系。
  5. mNativeObject = nativeCreate(session, name, w, h, format, flags);
  6. }
  1. static jlong nativeCreate(JNIEnv* env, jclass clazz, jobject sessionObj,
  2. jstring nameStr, jint w, jint h, jint format, jint flags) @android_view_SurfaceControl.cpp{
  3. // SurfaceComposerClient是surfaceflinger的代表,opengl es和surface都是在这个类的协助下申请和访问buffer缓冲区。这里是通过 android_view_SurfaceSession_getClient来获取client对象,那么是什么地方创建的呢?
  4. sp<SurfaceComposerClient> client(android_view_SurfaceSession_getClient(env, sessionObj));
  5. sp<SurfaceControl> surface = client->createSurface( String8(name.c_str()), w, h, format, flags);
  6. surface->incStrong((void *)nativeCreate);
  7. return reinterpret_cast<jlong>(surface.get());
  8. }

继续看哪里创建了client(SurfaceComposerClient)对象。从这个函数的实现,可以知道,这是从jni层获取java层的属性,所以创建相关类实例的地方应该在native层创建了对象,然后通过jni保存在了java层。

  1. sp<SurfaceComposerClient> android_view_SurfaceSession_getClient(
  2. JNIEnv* env, jobject surfaceSessionObj) @android_view_SurfaceSession.cpp{
  3. return reinterpret_cast<SurfaceComposerClient*>(
  4. env->GetLongField(surfaceSessionObj, gSurfaceSessionClassInfo.mNativeClient));
  5. }

具体过程,还要从addWindow看起。

  1. public int addWindow(…...)@WindowManagerService.java{
  2. //创建WindowState时,将session变量保存在WindowState 的变量mSession中。
  3. WindowState win = new WindowState(this, session, client, token…);
  4. //attach()的实现中,调用mSession的windowAddedLocked()方法。进一步生成了SurfaceSession实例mSurfaceSession(属于Session.java的变量)。
  5. win.attach();
  6. }

//在SurfaceSession的构造函数中,通过native方法创建一个到SurfaceFlinger的连接,就是SurfaceComposerClient实例,这是native的SurfaceComposerClient.cpp对象,这个对象保存在了SurfaceSession.java中的变量mNativeClient中。

  1. private long mNativeClient; // SurfaceComposerClient*
  2. public SurfaceSession() @SurfaceSession.java{
  3. mNativeClient = nativeCreate();
  4. }

在创建WindowState对象时,其构造函数中,同时创建了WindowStateAnimator对象,而且WindowStateAnimator.java的构造函数中也保存了Session对象到其变量mSession中。

  1. WindowStateAnimator(final WindowState win) @WindowStateAnimator.java{
  2. mSession = win.mSession;
  3. }

在调用WindowStateAnimator的createSurfaceLocked函数,创建WindowSurfaceController对象时,把mSession.mSurfaceSession传给了WindowSurfaceController的构造函数,在WindowSurfaceController的构造函数中,这个SurfaceSession对象传给了SurfaceControl。

现在我们直到SurfaceControl.java调用native函数nativeCreate时,获取的SurfaceComposerClient实例client是怎么来的了。

前面说了Surface是有SurfaceControl来管理的,SurfaceControl.java构造函数的nativeCreate就是建立跟surfaceflinger的连接,最终的surface的创建还要有SurfaceFlinger来完成。

  1. sp<SurfaceControl> SurfaceComposerClient::createSurface(
  2. const String8& name,
  3. uint32_t w,
  4. uint32_t h,
  5. PixelFormat format,
  6. uint32_t flags)@SurfaceComposerClient.cpp{
  7. sp<IGraphicBufferProducer> gbp;
  8. //调用Client.cpp的实现,创建IGraphicBufferProducer实例。
  9. status_t err = mClient->createSurface(name, w, h, format, flags,
  10. &handle, &gbp);
  11. //生成native层的 SurfaceControl对象,同时传入IGraphicBufferProducer对象。
  12. sur = new SurfaceControl(this, handle, gbp);
  13. }

回头看前面createSurfaceControl函数中获取surface的方式是surfaceController(WindowSurfaceController.java)的getSurface(outSurface);这个java层方法最终会调用SurfaceControl.cpp中的getSurface方法。

  1. sp<Surface> SurfaceControl::getSurface() const @SurfaceControl.cpp{
  2. mSurfaceData = new Surface(mGraphicBufferProducer, false);
  3. return mSurfaceData;
  4. }

可以看到这里创建了真正的Surface对象,当然这里的对象还是在server端,然后会通过writeToParcel写入reply。这样ViewRootImpl.java这边,也即是客户端就可以利用readFromParcel把它还原出来,实现了对ViewRootImpl.java中mSurface变量的填充。

  1. public int relayout(android.view.IWindow window, int seq, android.view.WindowManager.LayoutParams attrs, int requestedWidth, int requestedHeight, int viewVisibility, int flags, android.graphics.Rect outFrame, android.graphics.Rect outOverscanInsets, android.graphics.Rect outContentInsets, android.graphics.Rect outVisibleInsets, android.graphics.Rect outStableInsets, android.graphics.Rect outOutsets, android.graphics.Rect outBackdropFrame, android.content.res.Configuration outConfig, android.view.Surface outSurface) throws android.os.RemoteException@IWindowSession.java{
  2. //这里就是读取server端的返回值。Surface.java中的 readFromParcel调用了native层的实现nativeReadFromParcel。
  3. outSurface.readFromParcel(_reply);
  4. }

//可以看到客户端新创建了native层的Surface对象,所以和服务端的surface(native层)对象并不是同一个,但是跟surface关联的IGraphicBufferProducer是同一个,实际上Surface的主要职责就是管理用于存储UI数据的内存块。

  1. static jlong nativeReadFromParcel(JNIEnv* env, jclass clazz,
  2. jlong nativeObject, jobject parcelObj) @android_view_Surface.cpp{
  3. Parcel* parcel = parcelForJavaObject(env, parcelObj);
  4. android::view::Surface surfaceShim;
  5. surfaceShim.readFromParcel(parcel, /*nameAlreadyRead*/true);
  6. sp<Surface> sur;
  7. sur = new Surface(surfaceShim.graphicBufferProducer, true);
  8. sur->incStrong(&sRefBaseOwner);
  9. return jlong(sur.get());
  10. }

2),relayoutWindow中还有一个比较重要的调用performSurfacePlacement,功能包括两部分,一是performLayout,计算窗口大小,二是performSurface,对Surface属性的设置,如:setSize,setLayer,setPostion,然后这些变更会告知Surfaceflinger。

  1. public int relayoutWindow(Session session, IWindow client, int seq,
  2. WindowManager.LayoutParams attrs, int requestedWidth,
  3. int requestedHeight, int viewVisibility, int flags,
  4. Rect outFrame, Rect outOverscanInsets, Rect outContentInsets,
  5. Rect outVisibleInsets, Rect outStableInsets, Rect outOutsets, Rect outBackdropFrame,
  6. Configuration outConfig, Surface outSurface)@WindowManagerService.java {
  7. mWindowPlacerLocked.performSurfacePlacement();
  8. }

performSurfacePlacement间接调用了performSurfacePlacementInner。

//有些属性发生了变化,要在这里对变更做计算。

  1. private void performSurfacePlacementInner(boolean recoveringMemory) @WindowSurfacePlacer.java{
  2. //在处理surface属性前,先调用 openTransaction,然后对surface属性做处理,但是处理不是立即生效,而是要等到 closeTransaction业务关闭后,统一告知surfaceflinger才会生效。
  3. SurfaceControl.openTransaction();
  4. try {
  5. applySurfaceChangesTransaction(recoveringMemory, numDisplays, defaultDw, defaultDh);
  6. }finally {
  7. SurfaceControl.closeTransaction();
  8. }
  9. //获取默认显示屏的窗口列表。
  10. final WindowList defaultWindows = defaultDisplay.getWindowList();
  11.  
  12. //处理应用切换mService.mAppTransition相关的操作。
  13. defaultDisplay.pendingLayoutChanges |= handleAppTransitionReadyLocked(defaultWindows);
  14. defaultDisplay.pendingLayoutChanges |=mService.handleAnimatingStoppedAndTransitionLocked();
  15. //如果窗口不可见了,销毁他的surface。
  16. boolean wallpaperDestroyed = false;
  17. i = mService.mDestroySurface.size();
  18. if (i > 0) {
  19. //这里有while循环,处理mDestroySurface列表中的每个 WindowState。
  20. WindowState win = mService.mDestroySurface.get(i);
  21. win.destroyOrSaveSurface();
  22. mService.mDestroySurface.clear();
  23. }
  24.  
  25. //移除不在具有可见窗口的token。
  26. for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
  27. final DisplayContent displayContent = mService.mDisplayContents.valueAt(displayNdx);
  28. ArrayList<WindowToken> exitingTokens = displayContent.mExitingTokens;
  29. for (i = exitingTokens.size() - 1; i >= 0; i--) {
  30. WindowToken token = exitingTokens.get(i);
  31. exitingTokens.remove(i);
  32. mWallpaperControllerLocked.removeWallpaperToken(token);
  33. }
  34. }
  35.  
  36. //从task中移除退出的应用程序。
  37. for (int stackNdx = mService.mStackIdToStack.size() - 1; stackNdx >= 0; --stackNdx) {
  38. final AppTokenList exitingAppTokens =
  39. mService.mStackIdToStack.valueAt(stackNdx).mExitingAppTokens;
  40. AppWindowToken token = exitingAppTokens.get(i);
  41. token.mAppAnimator.clearAnimation();
  42. token.removeAppFromTaskLocked();
  43. }
  44.  
  45. //更新窗口信息到Inputdispatch,因为现在窗口更改已经稳定了。
  46. mService.mInputMonitor.updateInputWindowsLw(true /*force*/);
  47.  
  48. //安排动画的执行。
  49. mService.scheduleAnimationLocked();
  50. }
    1. private void applySurfaceChangesTransaction(boolean recoveringMemory, int numDisplays,
    2. int defaultDw, int defaultDh) @WindowSurfacePlacer.java{
    3. //循环处理每个显示设备,我们只关注主显示屏,
    4. final DisplayContent displayContent = mService.mDisplayContents.valueAt(displayNdx);
    5. WindowList windows = displayContent.getWindowList();
    6. DisplayInfo displayInfo = displayContent.getDisplayInfo();
    7. int repeats = 0;
    8. do {
    9. //while循环,6次后跳出,为什么是6次不知道?
    10. repeats++;
    11. if (repeats > 6) {
    12. displayContent.layoutNeeded = false;
    13. break;
    14. }
    15. //需要的化,计算窗口大小,这个 LAYOUT_REPEAT_THRESHOLD是4,定义在WindowManagerService.java中。
    16. if (repeats < LAYOUT_REPEAT_THRESHOLD) {
    17. performLayoutLockedInner(displayContent, repeats == 1,false /* updateInputWindows */);
    18. }
    19.  
    20. if (isDefaultDisplay) {
    21. //对每一个窗口,调用窗口策略policy(PhoneWindowManager.java)中的方法,应用policy。
    22. mService.mPolicy.beginPostLayoutPolicyLw(dw, dh);
    23. for (int i = windows.size() - 1; i >= 0; i--) {
    24. WindowState w = windows.get(i);
    25. if (w.mHasSurface) {
    26. mService.mPolicy.applyPostLayoutPolicyLw(w, w.mAttrs,
    27. w.mAttachedWindow);
    28. }
    29. }
    30. displayContent.pendingLayoutChanges |=mService.mPolicy.finishPostLayoutPolicyLw();
    31. }
    32. }while (displayContent.pendingLayoutChanges != 0);
    33.  
    34. //针对每个窗口,根据需要应用特效,动画相关等。
    35. for (int i = windows.size() - 1; i >= 0; i--) {
    36. WindowState w = windows.get(i);
    37. w.applyDimLayerIfNeeded();
    38. }
    39. }

Android 7.1 GUI系统-窗口管理WMS-Surface管理(四)的更多相关文章

  1. 图解Android - Android GUI 系统 (2) - 窗口管理 (View, Canvas, Window Manager)

    Android 的窗口管理系统 (View, Canvas, WindowManager) 在图解Android - Zygote 和 System Server 启动分析一 文里,我们已经知道And ...

  2. android Gui系统之WMS(2)----窗口的添加

    Android系统很多,但是最常用的就两类,一类是有系统进场管理的,系统窗口.还有一类就是由应用程序产生的,应用窗口. 1.系统窗口的添加流程 1.1 addStatusBarWindow Phone ...

  3. android Gui系统之WMS(1)----window flags & view flags

    SurfaceFlinger 前面说的,就是一个surface的合成.SurfaceFlinger就是一个默默的记录着,它不会对surface的内容有什么改动. WMS(WindowsManagerS ...

  4. android Gui系统之SurfaceFlinger(1)---SurfaceFlinger概论

    GUI 是任何系统都很重要的一块. android GUI大体分为4大块. 1)SurfaceFlinger 2)WMS 3)View机制 4)InputMethod 这块内容非常之多,但是理解后,可 ...

  5. 图解Android - Android GUI 系统 (5) - Android的Event Input System

    Android的用户输入处理 Android的用户输入系统获取用户按键(或模拟按键)输入,分发给特定的模块(Framework或应用程序)进行处理,它涉及到以下一些模块: Input Reader: ...

  6. android Gui系统之SurfaceFlinger(1)---SurfaceFlinger概论【转】

    转自:https://www.cnblogs.com/deman/p/5584198.html 阅读目录 1.OpenGL & OpenGL ES 2.Android的硬件接口HAL 3.An ...

  7. 图解Android - Android GUI 系统 (1) - 概论

    Android的GUI系统是Android最重要也最复杂的系统之一.它包括以下部分: 窗口和图形系统 - Window and View Manager System. 显示合成系统 - Surfac ...

  8. Android GUI系统

    图解Android - Android GUI 系统 (1) - 概论 图解Android - Android GUI 系统 (2) - 窗口管理系统 图解Android - Android GUI ...

  9. 图解Android - System Service 概论 和 Android GUI 系统

    通过 图解Android - Binder 和 Service 一文中,我们已经分析了Binder 和 Service的工作原理.接下来,我们来简要分析Android 系统里面都有哪些重要的Servi ...

随机推荐

  1. java中日期格式的转换和应用

    java中主要有3个类用于日期格式转换    DateFormat .SimpleDateFormat.Calendar SimpleDateFormat函数的继承关系: java.lang.Obje ...

  2. 谈 API 的撰写 - 子系统

    在做一个系统时,有一些子系统几乎是必备的:配置管理,CLI,以及测试框架. 配置管理 我们先说配置管理.一个系统的灵活度,和它的配置管理是离不开的.系统中存在的大量的预置的属性(下文简称 proper ...

  3. MFC中函数的使用

    函数语句: ((CStatic*)GetDlgItem(IDC_STATIC1))->SetIcon(AfxGetApp()->LoadIconW(IDI_CLOSE)); 解释: 1.G ...

  4. 使用Hadoop自己的类操作HDFS

    package hdfs; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.I ...

  5. VueJS路由

    Vue.js 路由 本章节我们将为大家介绍 Vue.js 路由. Vue.js 路由允许我们通过不同的 URL 访问不同的内容. 通过 Vue.js 可以实现多视图的单页Web应用(single pa ...

  6. 通俗的理解java的堆和栈

    堆 可以把堆理解为一家餐厅,里面有200张桌子,也就是最多能同时容纳200桌客人就餐,来一批客人就为他们安排一些桌子,如果某天来的客人特别多,超过200桌了,那就不能再接待超出的客人了.当然,进来吃饭 ...

  7. android开发系列之数据存储

    在我们的android实际开发过程,必不可少的一种行为操作对象就是数据.有些数据,对于用户而言是一次性的,这就要求我们每次进到App的时候,都需要去刷新数据.有些数据,对于用户而言又是具有一定时效性的 ...

  8. jQuery入门知识点

    <精通ASP.NET MVC3框架>第20章 1.jQuery文件jquery-1.5.1.js:jquey核心库常规版jquery-1.5.1.min.js:jquery核心库最小化版j ...

  9. 时间控件(DateTime Picker)

    中文:http://www.bootcss.com/p/bootstrap-datetimepicker/index.htm http://www.malot.fr/bootstrap-datetim ...

  10. python 基础 8.1 r 正则对象

                                                                                                        ...