美文网首页
SystemUI(三)扒一扒WindowManager的addV

SystemUI(三)扒一扒WindowManager的addV

作者: 付十一v | 来源:发表于2020-03-22 22:40 被阅读0次

从上面两篇SystemUI中发现StatusBar是通过WindowManager的addView()添加在界面上,那么内部Window是如何进行添加的?

带着疑问,跟踪到WindowManager.addView()方法中,由于WindowManager是一个接口,而实现它的是WindowManagerImpl.java

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

在WindowManagerImpl可以发现,最终进行addView操作的是WindowManagerGlobal这个类,接着跟踪进去,可以发现重头戏在WindowManagerGlobal这个类中,那么接下来就开始理清内部逻辑。

      public void addView(View view, ViewGroup.LayoutParams params,
279              Display display, Window parentWindow) {
280          if (view == null) {
281              throw new IllegalArgumentException("view must not be null");
282          }
283          if (display == null) {
284              throw new IllegalArgumentException("display must not be null");
285          }
286          if (!(params instanceof WindowManager.LayoutParams)) {
287              throw new IllegalArgumentException("Params must be WindowManager.LayoutParams");
288          }
289  
290          final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams) params;
291          if (parentWindow != null) {
292              parentWindow.adjustLayoutParamsForSubWindow(wparams);
293          } else {
294              // If there's no parent, then hardware acceleration for this view is
295              // set from the application's hardware acceleration setting.
296              final Context context = view.getContext();
297              if (context != null
298                      && (context.getApplicationInfo().flags
299                              & ApplicationInfo.FLAG_HARDWARE_ACCELERATED) != 0) {
300                  wparams.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
301              }
302          }
303  
304          ViewRootImpl root;
305          View panelParentView = null;
306  
307          synchronized (mLock) {
308              // Start watching for system property changes.
309              if (mSystemPropertyUpdater == null) {
310                  mSystemPropertyUpdater = new Runnable() {
311                      @Override public void run() {
312                          synchronized (mLock) {
313                              for (int i = mRoots.size() - 1; i >= 0; --i) {
314                                  mRoots.get(i).loadSystemProperties();
315                              }
316                          }
317                      }
318                  };
319                  SystemProperties.addChangeCallback(mSystemPropertyUpdater);
320              }
321  
322              int index = findViewLocked(view, false);
323              if (index >= 0) {
324                  if (mDyingViews.contains(view)) {
325                      // Don't wait for MSG_DIE to make it's way through root's queue.
326                      mRoots.get(index).doDie();
327                  } else {
328                      throw new IllegalStateException("View " + view
329                              + " has already been added to the window manager.");
330                  }
331                  // The previous removeView() had not completed executing. Now it has.
332              }
333  
334              // If this is a panel window, then find the window it is being
335              // attached to for future reference.
336              if (wparams.type >= WindowManager.LayoutParams.FIRST_SUB_WINDOW &&
337                      wparams.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
338                  final int count = mViews.size();
339                  for (int i = 0; i < count; i++) {
340                      if (mRoots.get(i).mWindow.asBinder() == wparams.token) {
341                          panelParentView = mViews.get(i);
342                      }
343                  }
344              }
345  
346           ...
365      }

在最开始280行-300行,对传进来的参数进行检查,view,display为null,params不属于WindomManager.LayoutParams都会抛出异常。另外如果是子Window,那么还需要通过adjustLayoutParamsForSubWindow(wparams)对布局参数进行调整。

在对参数进行检查后,首先通过findViewLocked查找到当前View的索引,并且判断当前view是否包含在mDyingViews(一个存储待删除的View的List集合)中,如果包含其中,则不等待MSG_DIE消息,直接调用doDie根据获取的索引进行删除。否则抛出异常。

在336处,如果是papanel window,则遍历所有View,获取papanel window所连接的view。准备工作已经做好,接下来就Window进行添加操作。

                root = new ViewRootImpl(view.getContext(), display);
347  
348              view.setLayoutParams(wparams);
349  
350              mViews.add(view);
351              mRoots.add(root);
352              mParams.add(wparams);
353  
354              // do this last because it fires off messages to start doing things
355              try {
356                  root.setView(view, wparams, panelParentView);
357              } catch (RuntimeException e) {
358                  // BadTokenException or InvalidDisplayException, clean up.
359                  if (index >= 0) {
360                      removeViewLocked(index, true);
361                  }
362                  throw e;
363              }
364          }

在上述代码的最后,通过ViewRootImpl.setView来更新界面.

public final class ViewRootImpl implements ViewParent,
          View.AttachInfo.Callbacks, ThreadedRenderer.DrawCallbacks { 
                ...
         public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
                    ...
            try {
755                      mOrigWindowType = mWindowAttributes.type;
756                      mAttachInfo.mRecomputeGlobalAttributes = true;
757                      collectViewAttributes();
758                      res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
759                              getHostVisibility(), mDisplay.getDisplayId(), mWinFrame,
760                              mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
761                              mAttachInfo.mOutsets, mAttachInfo.mDisplayCutout, mInputChannel);
762                  } catch (RemoteException e) {
                ...
            }
                    ...
}

758行,在setView方法中主要调用了mWindowSession的addToDisplay方法。mWindowSession属于IWindowSession类型,一个Binder对象,用于进行进程间通信,IWindowSession是Client端的代理,它的Server端的实现为Session,此前包含ViewRootImpl在内的代码逻辑都是运行在本地进程的,而Session的addToDisplay方法则运行在WMS所在的进程。


class Session extends IWindowSession.Stub implements IBinder.DeathRecipient {
        final WindowManagerService mService;
        ...
        @Override
201      public int addToDisplay(IWindow window, int seq, WindowManager.LayoutParams attrs,
202              int viewVisibility, int displayId, Rect outFrame, Rect outContentInsets,
203              Rect outStableInsets, Rect outOutsets,
204              DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel) {
205          return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId, outFrame,
206                  outContentInsets, outStableInsets, outOutsets, outDisplayCutout,           outInputChannel);
        ...
207      }
}

到了最后,可以发现addView其实是WindowManagerService进行addWindow操作。

Window的添加操作实际上是先通过WindowManagerGlobal对View进行第一步的处理,ViewRootImpl来进行界面的刷新,内部则通过Session与WindowManagerService进行跨进程通信,将添加的请求交给WindowManagerService来处理。

相关文章

  • SystemUI(三)扒一扒WindowManager的addV

    从上面两篇SystemUI中发现StatusBar是通过WindowManager的addView()添加在界面上...

  • 猫扒扒目录

    第一章:猫扒扒简介 第二章:猫扒扒添加商品 第三章:猫扒扒启动 第四章:猫扒扒接单演示 第五章:猫扒扒自动收取红包...

  • 扒一扒

    今天特别有感触,也不知是为何,就想书写一点点东西波动一下在这喧哗的世界已然沉寂已久的心。 都说扒开人的内心,会有两...

  • 猫扒扒启动

    开始启动猫扒扒 1,启动并登陆微信 2,点击启动服务 3,自动跳转微信成功 猫扒扒介绍:猫扒扒是一款 为微商打造的...

  • 看看就得了呗! 扒,扒你妹啊扒!!!

  • 扒一扒RPC

    前言:本篇文章是继JDK动态代理超详细源码分析之后的,因为RPC是基于动态代理的。想必大家都听过RPC,但是可能并...

  • 扒一扒DOM

    目录1.什么是DOM2.节点的概念3.节点的属性和方法4.Element对象的属性和方法5.Attribute对象...

  • 扒一扒鲁迅

    横眉冷对千夫指,俯首甘为孺子牛。 说起这鲁迅先生,许多人脑海里立马蹬蹬蹬蹦出三大家——“文学家”、“思想家”、“革...

  • 每日一画——板绘或指绘day·11

    扒扒以前的画

  • 二四六

    零六零二一扒仨扒

网友评论

      本文标题:SystemUI(三)扒一扒WindowManager的addV

      本文链接:https://www.haomeiwen.com/subject/ioncnctx.html