Andorid 图形系统

766 阅读17分钟

参考连接: www.jianshu.com/p/b3a1ea792…

1. Window 加载视图过程

1. 了解整体视图关系

img

Activity: 本身不是窗口,也不是视图,只是窗口的载体,一方面是 key, touch 事件的响应处理,一方面是对界面生命周期做统一调度。

Window: 一个顶级窗口查看和行为的一个抽象基类,也是装载View 的原始容器,处理一些应用窗口通用的逻辑。使用时到的是它的唯一实现类: PhoneWindow 。 Window 受 WindowManager 统一管理。

DecorView: 顶级视图,一般情况下它内部会包含一个竖直方向的LinearLayout ,上面的标题栏(titleBar),下面是内容栏。通常我们在 Activity 中通过 setContentView 所设置的布局文件就是被加载到 id 为 android.R.id.content 的内容栏里(FrameLayout)。

2. Window 的类型

添加窗口是通过 WindowManagerGlobal 的 addView 方法操作的,有三个必要参数:

  1. view : 表示要显示的 View, 一般是对该 view 的上下文进行操作。(view.getContext())
  2. display : 表示要输出的显示设备
  3. params : 类型WindowManager.LayoutParams. 即表示该View要展示在窗口上的布局参数。 ( flags, type)
  • flags:表示Window的属性:

    • FLAG_NOT_FOCUSABLE
    • FLAG_NOT_TOUCH_MODEAL
    • FLAG_SHOW_WHEN_LOCKED
  • type: 表示窗口的类型

    • system window 独立存在
    • application window 属于应用的窗口
    • sub window 需要依附于父window, 不能独立存在

Window 是分层的,每个Window都有对应的 z-ordered (z轴, 从1—2999,) 层级大的会覆盖在层级小的Window 上面,另外有些系统层级的使用是需要声明权限的。

windowmanager 的 layoutParms 中的 token 主要作用是为了维护activity和window 的对应关系。

3. Window 的创建

img

对于window 的创建,我们从 handleLaunchActivity 开始看源码:

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

    public Activity handleLaunchActivity(ActivityClientRecord r,
3938              PendingTransactionActions pendingActions, Intent customIntent) {
3939          // If we are getting ready to gc after going to the background, well
3940          // we are back active so skip it.
3941          unscheduleGcIdler();
3942          mSomeActivitiesChanged = true;
3943  
3944          if (r.profilerInfo != null) {
3945              mProfiler.setProfiler(r.profilerInfo);
3946              mProfiler.startProfiling();
3947          }
3948  
3949          if (r.mPendingFixedRotationAdjustments != null) {
3950              // The rotation adjustments must be applied before handling configuration, so process
3951              // level display metrics can be adjusted.
3952              overrideApplicationDisplayAdjustments(r.token, adjustments ->
3953                      adjustments.setFixedRotationAdjustments(r.mPendingFixedRotationAdjustments));
3954          }
3955  
3956          // Make sure we are running with the most recent config.
3957          mConfigurationController.handleConfigurationChanged(null, null);
3958  
3959          if (localLOGV) Slog.v(
3960              TAG, "Handling launch of " + r);
3961  
3962          // Initialize before creating the activity
3963          if (ThreadedRenderer.sRendererEnabled
3964                  && (r.activityInfo.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0) {
3965              HardwareRenderer.preload();
3966          }
3967          WindowManagerGlobal.initialize();
3968  
3969          // Hint the GraphicsEnvironment that an activity is launching on the process.
3970          GraphicsEnvironment.hintActivityLaunch();
3971  
3972          final Activity a = performLaunchActivity(r, customIntent);
3973  
3974          if (a != null) {
3975              r.createdConfig = new Configuration(mConfigurationController.getConfiguration());
3976              reportSizeConfigurations(r);
3977              if (!r.activity.mFinished && pendingActions != null) {
3978                  pendingActions.setOldState(r.state);
3979                  pendingActions.setRestoreInstanceState(true);
3980                  pendingActions.setCallOnPostCreate(true);
3981              }
3982          } else {
3983              // If there was an error, for any reason, tell the activity manager to stop us.
3984              ActivityClient.getInstance().finishActivity(r.token, Activity.RESULT_CANCELED,
3985                      null /* resultData */, Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
3986          }
3987  
3988          return a;
3989      }
    

final Activity a = performLaunchActivity(r, customIntent); 关注Activity的 attach 方法:

 final void attach(Context context, ActivityThread aThread,
8507              Instrumentation instr, IBinder token, int ident,
8508              Application application, Intent intent, ActivityInfo info,
8509              CharSequence title, Activity parent, String id,
8510              NonConfigurationInstances lastNonConfigurationInstances,
8511              Configuration config, String referrer, IVoiceInteractor voiceInteractor,
8512              Window window, ActivityConfigCallback activityConfigCallback, IBinder assistToken,
8513              IBinder shareableActivityToken) {
                // 绑定上下文
8514          attachBaseContext(context);
8515  
8516          mFragments.attachHost(null /*parent*/);
8517          // 创建 Window , PhoneWindow  Window 的唯一具体实现类 
8518          mWindow = new PhoneWindow(this, window, activityConfigCallback);
8519          mWindow.setWindowControllerCallback(mWindowControllerCallback);
8520          mWindow.setCallback(this);
8521          mWindow.setOnWindowDismissedCallback(this);
8522          mWindow.getLayoutInflater().setPrivateFactory(this);
8523          if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) {
8524              mWindow.setSoftInputMode(info.softInputMode);
8525          }
8526          if (info.uiOptions != 0) {
8527              mWindow.setUiOptions(info.uiOptions);
8528          }
8529          mUiThread = Thread.currentThread();
8530  
8531          mMainThread = aThread;
8532          mInstrumentation = instr;
8533          mToken = token;
8534          mAssistToken = assistToken;
8535          mShareableActivityToken = shareableActivityToken;
8536          mIdent = ident;
8537          mApplication = application;
8538          mIntent = intent;
8539          mReferrer = referrer;
8540          mComponent = intent.getComponent();
8541          mActivityInfo = info;
8542          mTitle = title;
8543          mParent = parent;
8544          mEmbeddedID = id;
8545          mLastNonConfigurationInstances = lastNonConfigurationInstances;
8546          if (voiceInteractor != null) {
8547              if (lastNonConfigurationInstances != null) {
8548                  mVoiceInteractor = lastNonConfigurationInstances.voiceInteractor;
8549              } else {
8550                  mVoiceInteractor = new VoiceInteractor(voiceInteractor, this, this,
8551                          Looper.myLooper());
8552              }
8553          }
8554        // 设置 WindowManager
8555          mWindow.setWindowManager(
8556                  (WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
8557                  mToken, mComponent.flattenToString(),
8558                  (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
8559          if (mParent != null) {
8560              mWindow.setContainer(mParent.getWindow());
8561          }
            //  创建完成以后通过getWindowManager 就可以得到 WindowManager 实例
8562          mWindowManager = mWindow.getWindowManager(); // 其实它是 WindowManagerImpl
8563          mCurrentConfig = config;
8564  
8565          mWindow.setColorMode(info.colorMode);
8566          mWindow.setPreferMinimalPostProcessing(
8567                  (info.flags & ActivityInfo.FLAG_PREFER_MINIMAL_POST_PROCESSING) != 0);
8568  
8569          setAutofillOptions(application.getAutofillOptions());
8570          setContentCaptureOptions(application.getContentCaptureOptions());
8571  
8572          try {
8573              mClipboardManager = new ClipboardManager(context, null);
8574          } catch (Exception e) {
8575              Slog.w(TAG, "ClipboardManager get failed", e);
8576          }
8577  
8578      }

这里创建了一个 PhoneWindow对象,并且实现了 Window 的 Callback 接口,这样 Activity 就和 Window 关联在了一起,并且通过 callback 能够接受 key 和 touch 事件。

此外,初始化且设置 WindowManager ,每个 Activity 会有一个 WindowManager 对象,这个 mWindowManager 就是和 WindowManagerService 进行通信,也是 WindowManagerService 识别 View 具体属于哪个 Activity 的关键,创建时传入 IBinder 类型的 mToken.

我们从 window 的 setWindowManager 方法出发,很容易找到 WindowManager 这个接口的具体实现是 WindowManagerImpl。

4. Window 添加 View 过程

虽然PhoneWindow 对 View 来说更多是 扮演容器的角色,但真正完成把一个 View ,作为窗口添加到 WMS 的过程是由 WindowManager 来完成的。而且从上面创建过程我们知道了 WindowManager 的具体实现是 WindowManagerImpl.

那么我们继续来跟代码:

从上面 handleLaunchActivity 的代码中 performLaunchActivity后面,有个 handleResumeActivity ,从名字可以看出,跟 activity onResume 相关:

public void handleResumeActivity(ActivityClientRecord r, boolean finalStateRequest,
5155              boolean isForward, String reason) {
5156          // If we are getting ready to gc after going to the background, well
5157          // we are back active so skip it.
5158          unscheduleGcIdler();
5159          mSomeActivitiesChanged = true;
5160  
5161          // TODO Push resumeArgs into the activity for consideration
5162          // skip below steps for double-resume and r.mFinish = true case.
5163          if (!performResumeActivity(r, finalStateRequest, reason)) {
5164              return;
5165          }
5166          if (mActivitiesToBeDestroyed.containsKey(r.token)) {
5167              // Although the activity is resumed, it is going to be destroyed. So the following
5168              // UI operations are unnecessary and also prevents exception because its token may
5169              // be gone that window manager cannot recognize it. All necessary cleanup actions
5170              // performed below will be done while handling destruction.
5171              return;
5172          }
5173  
5174          final Activity a = r.activity;
5175          /** ZTE add for app datacollection begin*/
5176          if (r.packageInfo != null) {
5177              packageName = r.packageInfo.mPackageName;
5178          }
5179          /** ZTE add for app datacollection end*/
5180  
5181          if (localLOGV) {
5182              Slog.v(TAG, "Resume " + r + " started activity: " + a.mStartedActivity
5183                      + ", hideForNow: " + r.hideForNow + ", finished: " + a.mFinished);
5184          }
5185  
5186          final int forwardBit = isForward
5187                  ? WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION : 0;
5188  
5189          // If the window hasn't yet been added to the window manager,
5190          // and this guy didn't finish itself or start another activity,
5191          // then go ahead and add the window.
5192          boolean willBeVisible = !a.mStartedActivity;
5193          if (!willBeVisible) {
5194              willBeVisible = ActivityClient.getInstance().willActivityBeVisible(
5195                      a.getActivityToken());
5196          }
5197          if (r.window == null && !a.mFinished && willBeVisible) {
5198              r.window = r.activity.getWindow();
5199              View decor = r.window.getDecorView();
5200              decor.setVisibility(View.INVISIBLE);
5201              ViewManager wm = a.getWindowManager();
5202              WindowManager.LayoutParams l = r.window.getAttributes();
5203              a.mDecor = decor;
5204              l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
5205              l.softInputMode |= forwardBit;
5206              if (r.mPreserveWindow) {
5207                  a.mWindowAdded = true;
5208                  r.mPreserveWindow = false;
5209                  // Normally the ViewRoot sets up callbacks with the Activity
5210                  // in addView->ViewRootImpl#setView. If we are instead reusing
5211                  // the decor view we have to notify the view root that the
5212                  // callbacks may have changed.
5213                  ViewRootImpl impl = decor.getViewRootImpl();
5214                  if (impl != null) {
5215                      impl.notifyChildRebuilt();
5216                  }
5217              }
5218              if (a.mVisibleFromClient) {
5219                  if (!a.mWindowAdded) {
5220                      a.mWindowAdded = true;
5221                      wm.addView(decor, l); // 把decor添加到窗口上(化重点)
5222                  } else {
5223                      // The activity will get a callback for this {@link LayoutParams} change
5224                      // earlier. However, at that time the decor will not be set (this is set
5225                      // in this method), so no action will be taken. This call ensures the
5226                      // callback occurs with the decor set.
5227                      a.onWindowAttributesChanged(l);
5228                  }
5229              }
5230  
5231              // If the window has already been added, but during resume
5232              // we started another activity, then don't yet make the
5233              // window visible.
5234          } else if (!willBeVisible) {
5235              if (localLOGV) Slog.v(TAG, "Launch " + r + " mStartedActivity set");
5236              r.hideForNow = true;
5237          }
5238  
5239          // Get rid of anything left hanging around.
5240          cleanUpPendingRemoveWindows(r, false /* force */);
5241  
5242          // The window is now visible if it has been added, we are not
5243          // simply finishing, and we are not starting another activity.
5244          if (!r.activity.mFinished && willBeVisible && r.activity.mDecor != null && !r.hideForNow) {
5245              if (localLOGV) Slog.v(TAG, "Resuming " + r + " with isForward=" + isForward);
5246              ViewRootImpl impl = r.window.getDecorView().getViewRootImpl();
5247              WindowManager.LayoutParams l = impl != null
5248                      ? impl.mWindowAttributes : r.window.getAttributes();
5249              if ((l.softInputMode
5250                      & WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION)
5251                      != forwardBit) {
5252                  l.softInputMode = (l.softInputMode
5253                          & (~WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION))
5254                          | forwardBit;
5255                  if (r.activity.mVisibleFromClient) {
5256                      ViewManager wm = a.getWindowManager();
5257                      View decor = r.window.getDecorView();
5258                      wm.updateViewLayout(decor, l); // 更新窗口状态
5259                  }
5260              }
5261  
5262              r.activity.mVisibleFromServer = true;
5263              mNumVisibleActivities++;
5264              if (r.activity.mVisibleFromClient) {
                    // 已经成功添加到窗口上了(绘制和事件接收),设置为可见
5265                  r.activity.makeVisible();
5266              }
5267          }
5268  
5269          r.nextIdle = mNewActivities;
5270          mNewActivities = r;
5271          if (localLOGV) Slog.v(TAG, "Scheduling idle handler for " + r);
5272          Looper.myQueue().addIdleHandler(new Idler());
5273      }

wm是activity getWindowManager() 获取的, 那不就是WindowManagerImpl 的 addView 方法么,继续追!

if (!a.mWindowAdded) {
5220                      a.mWindowAdded = true;
5221                      wm.addView(decor, l); // 把decor添加到窗口上(化重点)
// WindowManagerImpl.java
@Override
131      public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
132          android.util.SeempLog.record_vg_layout(383,params);
133          applyTokens(params);
134          mGlobal.addView(view, params, mContext.getDisplayNoVerify(), mParentWindow,
135                  mContext.getUserId());
136      }

我们看到又代理了一层: mGlobal

之前 window 类型的时候有 WindowManagerGlobal

所以这个 WindowManagerImpl 其实也不干活,对于 Window(或者说是 View)的操作都是交由 WindowManagerGlobal 来处理, WindowManagerGlobal 以工厂的形式向外提供自己的实例。这种工作模式是桥接模式,将所有的操作全部委托给 WindowManagerGlobal 来实现。

在WindowManagerImpl 的全局变量中通过单例模式初始化了 WindowManagerGlobal , 也就是说一个进程就只有一个 WindowManagerGlobal 对象。

public void addView(View view, ViewGroup.LayoutParams params,
325              Display display, Window parentWindow, int userId) {
326          if (view == null) {
327              throw new IllegalArgumentException("view must not be null");
328          }
329          if (display == null) {
330              throw new IllegalArgumentException("display must not be null");
331          }
332          if (!(params instanceof WindowManager.LayoutParams)) {
333              throw new IllegalArgumentException("Params must be WindowManager.LayoutParams");
334          }
335  
336          final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams) params;
337          if (parentWindow != null) {
                // 调整布局参数,并设置 token
338              parentWindow.adjustLayoutParamsForSubWindow(wparams);
339          } else {
340              // If there's no parent, then hardware acceleration for this view is
341              // set from the application's hardware acceleration setting.
342              final Context context = view.getContext();
343              if (context != null
344                      && (context.getApplicationInfo().flags
345                              & ApplicationInfo.FLAG_HARDWARE_ACCELERATED) != 0) {
346                  wparams.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
347              }
348          }
349  
350          ViewRootImpl root;
351          View panelParentView = null;
352  
353          synchronized (mLock) {
354              // Start watching for system property changes.
355              if (mSystemPropertyUpdater == null) {
356                  mSystemPropertyUpdater = new Runnable() {
357                      @Override public void run() {
358                          synchronized (mLock) {
359                              for (int i = mRoots.size() - 1; i >= 0; --i) {
360                                  mRoots.get(i).loadSystemProperties();
361                              }
362                          }
363                      }
364                  };
365                  SystemProperties.addChangeCallback(mSystemPropertyUpdater);
366              }
367  
368              int index = findViewLocked(view, false);
369              if (index >= 0) {
370                  if (mDyingViews.contains(view)) {
                        // 如果待删除的View 中有当前 View ,删除它
371                      // Don't wait for MSG_DIE to make it's way through root's queue.
372                      mRoots.get(index).doDie();
373                  } else {
374                      throw new IllegalStateException("View " + view
375                              + " has already been added to the window manager.");
376                  }
377                  // The previous removeView() had not completed executing. Now it has.
                    // 之前移除View 并没有完成删除操作,现在正式删除该View
378              }
379  
380              // If this is a panel window, then find the window it is being
381              // attached to for future reference.
                // 如果这是一个子窗口(popupWidow),找到它的父窗口
                // 最本质的作用是使用父窗口的token(viewRootImpl的W类,也就是 Iwindow)
382              if (wparams.type >= WindowManager.LayoutParams.FIRST_SUB_WINDOW &&
383                      wparams.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
384                  final int count = mViews.size();
385                  for (int i = 0; i < count; i++) {
386                      if (mRoots.get(i).mWindow.asBinder() == wparams.token) {
                            // 在源码中token一般代表的是Binder对象,作用于IPC进程间数据通讯,并且它包含着
                            // 此次通讯所需要的信息
                            // 在ViewRootImpl里,token用来表示mWindow(W类,即Iwindow)
                            // 并且在wms中只有符合要求的token才能让window正常显示
387                          panelParentView = mViews.get(i);
388                      }
389                  }
390              }
391             // 创建ViewRootImpl,并且将 view 与之绑定
392              root = new ViewRootImpl(view.getContext(), display);
393  
394              view.setLayoutParams(wparams);
395  
396              mViews.add(view); // 将当前view添加到mViews集合中,mViews存储所有Window对应的View
397              mRoots.add(root);// 将当前ViewRootImpl添加到mRoots集合中,mRoots存储所有Window对应的ViewRootImpl
    
398              mParams.add(wparams);// 将当前window的params添加到mParams集合中,存储所有Window对应的布局参数
399  
400              // / M: Add log for tracking mViews.
401              Log.d("WindowClient", "Add to mViews: " + view + ", this = " + this
402                      + "mViews.size()=" + mViews.size());
403  
404              if (checkAppShouldExit(view)) {
405                  System.exit(0);
406              }
407  
408              // do this last because it fires off messages to start doing things
409              try {
                //通过ViewRootImpl 的setView方法,完成view的绘制流程,并添加到 window上。
410                  root.setView(view, wparams, panelParentView, userId);
411              } catch (RuntimeException e) {
412                  // BadTokenException or InvalidDisplayException, clean up.
413                  Log.d("WindowClient", "get RuntimeException");
414                  index = findViewLocked(view, false);
415                  if (index >= 0) {
416                      removeViewLocked(index, true);
417                  }
418                  throw e;
419              }
420          }
421      }

最最重要的是: root.setView(view, wparams, panelParentView); 一方面触发绘制流程,一方面把view添加到window上。

在这之前,先普及一下 WindowManager 与 WindowManagerService binder IPC 的两个接口:

  • IWindowSession : 应用程序向 WMS 请求功能 实现类: Session
  • IWindow: WMS 向客户端反馈它想确认的信息 实现类: W

img

下面看看ViewRootImpl 的 setView:

// ViewRootImpl
 public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView,
1031              int userId) {
1032          synchronized (this) {
1033              if (mView == null) {
1034                  mView = view;
1035  
1036                  mAttachInfo.mDisplayState = mDisplay.getState();
1037                  mDisplayManager.registerDisplayListener(mDisplayListener, mHandler);
1038  
1039                  mViewLayoutDirectionInitial = mView.getRawLayoutDirection();
1040                  mFallbackEventHandler.setView(view);
1041                  mWindowAttributes.copyFrom(attrs);
1042                  if (mWindowAttributes.packageName == null) {
1043                      mWindowAttributes.packageName = mBasePackageName;
1044                  }
1045                  mWindowAttributes.privateFlags |=
1046                          WindowManager.LayoutParams.PRIVATE_FLAG_USE_BLAST;
1047  
1048                  attrs = mWindowAttributes;
1049                  setTag();
1050  
1051                  if (DEBUG_KEEP_SCREEN_ON && (mClientWindowLayoutFlags
1052                          & WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) != 0
1053                          && (attrs.flags&WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) == 0) {
1054                      Slog.d(mTag, "setView: FLAG_KEEP_SCREEN_ON changed from true to false!");
1055                  }
1056                  // Keep track of the actual window flags supplied by the client.
1057                  mClientWindowLayoutFlags = attrs.flags;
1058  
1059                  setAccessibilityFocus(null, null);
1060  
1061                  if (view instanceof RootViewSurfaceTaker) {
1062                      mSurfaceHolderCallback =
1063                              ((RootViewSurfaceTaker)view).willYouTakeTheSurface();
1064                      if (mSurfaceHolderCallback != null) {
1065                          mSurfaceHolder = new TakenSurfaceHolder();
1066                          mSurfaceHolder.setFormat(PixelFormat.UNKNOWN);
1067                          mSurfaceHolder.addCallback(mSurfaceHolderCallback);
1068                      }
1069                  }
1070  
1071                  // Compute surface insets required to draw at specified Z value.
1072                  // TODO: Use real shadow insets for a constant max Z.
1073                  if (!attrs.hasManualSurfaceInsets) {
1074                      attrs.setSurfaceInsets(view, false /*manual*/, true /*preservePrevious*/);
1075                  }
1076  
1077                  CompatibilityInfo compatibilityInfo =
1078                          mDisplay.getDisplayAdjustments().getCompatibilityInfo();
1079                  mTranslator = compatibilityInfo.getTranslator();
1080  
1081                  // If the application owns the surface, don't enable hardware acceleration
1082                  if (mSurfaceHolder == null) {
1083                      // While this is supposed to enable only, it can effectively disable
1084                      // the acceleration too.
1085                      enableHardwareAcceleration(attrs);
1086                      final boolean useMTRenderer = MT_RENDERER_AVAILABLE
1087                              && mAttachInfo.mThreadedRenderer != null;
1088                      if (mUseMTRenderer != useMTRenderer) {
1089                          // Shouldn't be resizing, as it's done only in window setup,
1090                          // but end just in case.
1091                          endDragResizing();
1092                          mUseMTRenderer = useMTRenderer;
1093                      }
1094                  }
1095  
1096                  boolean restore = false;
1097                  if (mTranslator != null) {
1098                      mSurface.setCompatibilityTranslator(mTranslator);
1099                      restore = true;
1100                      attrs.backup();
1101                      mTranslator.translateWindowLayout(attrs);
1102                  }
1103                  if (DEBUG_LAYOUT) Log.d(mTag, "WindowLayout in setView:" + attrs);
1104  
1105                  if (!compatibilityInfo.supportsScreen()) {
1106                      attrs.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
1107                      mLastInCompatMode = true;
1108                  }
1109  
1110                  mSoftInputMode = attrs.softInputMode;
1111                  mWindowAttributesChanged = true;
1112                  mAttachInfo.mRootView = view;
1113                  mAttachInfo.mScalingRequired = mTranslator != null;
1114                  mAttachInfo.mApplicationScale =
1115                          mTranslator == null ? 1.0f : mTranslator.applicationScale;
1116                  if (panelParentView != null) {
1117                      mAttachInfo.mPanelParentWindowToken
1118                              = panelParentView.getApplicationWindowToken();
1119                  }
1120                  mAdded = true;
1121                  int res; /* = WindowManagerImpl.ADD_OKAY; */
1122  
1123                  if (ActivityThread.ZTE_TRAVERSAL_ACCELERATE_ENABLED) {
1124                      // nubia add for app launch traversals accelerate
1125                      startAppTraversalsAccelerate(mView);
1126                      // nubia add end
1127                  }
1128  
1129                  // Schedule the first layout -before- adding to the window
1130                  // manager, to make sure we do the relayout before receiving
1131                  // any other events from the system.
       // 在Window add 之前调用,确保UI布局完成-->measure, layout , draw
1132                  requestLayout(); //  View的绘制流程
1133                  InputChannel inputChannel = null;
1134                  if ((mWindowAttributes.inputFeatures
1135                          & WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) {
1136                      inputChannel = new InputChannel();
1137                  }
1138                  mForceDecorViewVisibility = (mWindowAttributes.privateFlags
1139                          & PRIVATE_FLAG_FORCE_DECOR_VIEW_VISIBILITY) != 0;
1140  
1141                  if (mView instanceof RootViewSurfaceTaker) {
1142                      PendingInsetsController pendingInsetsController =
1143                              ((RootViewSurfaceTaker) mView).providePendingInsetsController();
1144                      if (pendingInsetsController != null) {
1145                          pendingInsetsController.replayAndAttach(mInsetsController);
1146                      }
1147                  }
1148  
1149                  try {
1150                      mOrigWindowType = mWindowAttributes.type;
1151                      mAttachInfo.mRecomputeGlobalAttributes = true;
1152                      collectViewAttributes();
1153                      adjustLayoutParamsForCompatibility(mWindowAttributes);
1154                      controlInsetsForCompatibility(mWindowAttributes);
1155                      res = mWindowSession.addToDisplayAsUser(mWindow, mWindowAttributes,
1156                              getHostVisibility(), mDisplay.getDisplayId(), userId,
1157                              mInsetsController.getRequestedVisibility(), inputChannel, mTempInsets,
1158                              mTempControls);
1159                      if (mTranslator != null) {
1160                          mTranslator.translateInsetsStateInScreenToAppWindow(mTempInsets);
1161                          mTranslator.translateSourceControlsInScreenToAppWindow(mTempControls);
1162                      }
1163                  } catch (RemoteException e) {
1164                      mAdded = false;
1165                      mView = null;
1166                      mAttachInfo.mRootView = null;
1167                      mFallbackEventHandler.setView(null);
1168                      unscheduleTraversals();
1169                      setAccessibilityFocus(null, null);
1170                      throw new RuntimeException("Adding window failed", e);
1171                  } finally {
1172                      if (restore) {
1173                          attrs.restore();
1174                      }
1175                  }
1176  
1177                  mAttachInfo.mAlwaysConsumeSystemBars =
1178                          (res & WindowManagerGlobal.ADD_FLAG_ALWAYS_CONSUME_SYSTEM_BARS) != 0;
1179                  mPendingAlwaysConsumeSystemBars = mAttachInfo.mAlwaysConsumeSystemBars;
1180                  mInsetsController.onStateChanged(mTempInsets);
1181                  mInsetsController.onControlsChanged(mTempControls);
1182                  computeWindowBounds(mWindowAttributes, mInsetsController.getState(),
1183                          getConfiguration().windowConfiguration.getBounds(), mTmpFrames.frame);
1184                  setFrame(mTmpFrames.frame);
1185                  if (DEBUG_LAYOUT) Log.v(mTag, "Added window " + mWindow);
1186                  if (res < WindowManagerGlobal.ADD_OKAY) {
1187                      mAttachInfo.mRootView = null;
1188                      mAdded = false;
1189                      mFallbackEventHandler.setView(null);
1190                      unscheduleTraversals();
1191                      setAccessibilityFocus(null, null);
1192                      switch (res) {
1193                          case WindowManagerGlobal.ADD_BAD_APP_TOKEN:
1194                          case WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN:
1195                              throw new WindowManager.BadTokenException(
1196                                      "Unable to add window -- token " + attrs.token
1197                                      + " is not valid; is your activity running?");
1198                          case WindowManagerGlobal.ADD_NOT_APP_TOKEN:
1199                              throw new WindowManager.BadTokenException(
1200                                      "Unable to add window -- token " + attrs.token
1201                                      + " is not for an application");
1202                          case WindowManagerGlobal.ADD_APP_EXITING:
1203                              throw new WindowManager.BadTokenException(
1204                                      "Unable to add window -- app for token " + attrs.token
1205                                      + " is exiting");
1206                          case WindowManagerGlobal.ADD_DUPLICATE_ADD:
1207                              throw new WindowManager.BadTokenException(
1208                                      "Unable to add window -- window " + mWindow
1209                                      + " has already been added");
1210                          case WindowManagerGlobal.ADD_STARTING_NOT_NEEDED:
1211                              // Silently ignore -- we would have just removed it
1212                              // right away, anyway.
1213                              return;
1214                          case WindowManagerGlobal.ADD_MULTIPLE_SINGLETON:
1215                              throw new WindowManager.BadTokenException("Unable to add window "
1216                                      + mWindow + " -- another window of type "
1217                                      + mWindowAttributes.type + " already exists");
1218                          case WindowManagerGlobal.ADD_PERMISSION_DENIED:
1219                              throw new WindowManager.BadTokenException("Unable to add window "
1220                                      + mWindow + " -- permission denied for window type "
1221                                      + mWindowAttributes.type);
1222                          case WindowManagerGlobal.ADD_INVALID_DISPLAY:
1223                              throw new WindowManager.InvalidDisplayException("Unable to add window "
1224                                      + mWindow + " -- the specified display can not be found");
1225                          case WindowManagerGlobal.ADD_INVALID_TYPE:
1226                              throw new WindowManager.InvalidDisplayException("Unable to add window "
1227                                      + mWindow + " -- the specified window type "
1228                                      + mWindowAttributes.type + " is not valid");
1229                          case WindowManagerGlobal.ADD_INVALID_USER:
1230                              throw new WindowManager.BadTokenException("Unable to add Window "
1231                                      + mWindow + " -- requested userId is not valid");
1232                      }
1233                      throw new RuntimeException(
1234                              "Unable to add window -- unknown error code " + res);
1235                  }
1236  
1237                  if ((res & WindowManagerGlobal.ADD_FLAG_USE_BLAST) != 0) {
1238                      mUseBLASTAdapter = true;
1239                  }
1240  
1241                  if (view instanceof RootViewSurfaceTaker) {
1242                      mInputQueueCallback =
1243                          ((RootViewSurfaceTaker)view).willYouTakeTheInputQueue();
1244                  }
1245                  if (inputChannel != null) {
1246                      if (mInputQueueCallback != null) {
1247                          mInputQueue = new InputQueue();
1248                          mInputQueueCallback.onInputQueueCreated(mInputQueue);
1249                      }
1250                      mInputEventReceiver = new WindowInputEventReceiver(inputChannel,
1251                              Looper.myLooper());
1252  
1253                      if (ENABLE_INPUT_LATENCY_TRACKING && mAttachInfo.mThreadedRenderer != null) {
1254                          InputMetricsListener listener = new InputMetricsListener();
1255                          mHardwareRendererObserver = new HardwareRendererObserver(
1256                                  listener, listener.data, mHandler, true /*waitForPresentTime*/);
1257                          mAttachInfo.mThreadedRenderer.addObserver(mHardwareRendererObserver);
1258                      }
1259                  }
1260  
1261                  view.assignParent(this);
1262                  mAddedTouchMode = (res & WindowManagerGlobal.ADD_FLAG_IN_TOUCH_MODE) != 0;
1263                  mAppVisible = (res & WindowManagerGlobal.ADD_FLAG_APP_VISIBLE) != 0;
1264  
1265                  if (mAccessibilityManager.isEnabled()) {
1266                      mAccessibilityInteractionConnectionManager.ensureConnection();
1267                  }
1268  
1269                  if (view.getImportantForAccessibility() == View.IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
1270                      view.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
1271                  }
1272  
1273                  // Set up the input pipeline.
1274                  CharSequence counterSuffix = attrs.getTitle();
1275                  mSyntheticInputStage = new SyntheticInputStage();
1276                  InputStage viewPostImeStage = new ViewPostImeInputStage(mSyntheticInputStage);
1277                  InputStage nativePostImeStage = new NativePostImeInputStage(viewPostImeStage,
1278                          "aq:native-post-ime:" + counterSuffix);
1279                  InputStage earlyPostImeStage = new EarlyPostImeInputStage(nativePostImeStage);
1280                  InputStage imeStage = new ImeInputStage(earlyPostImeStage,
1281                          "aq:ime:" + counterSuffix);
1282                  InputStage viewPreImeStage = new ViewPreImeInputStage(imeStage);
1283                  InputStage nativePreImeStage = new NativePreImeInputStage(viewPreImeStage,
1284                          "aq:native-pre-ime:" + counterSuffix);
1285  
1286                  mFirstInputStage = nativePreImeStage;
1287                  mFirstPostImeInputStage = earlyPostImeStage;
1288                  mPendingInputEventQueueLengthCounterName = "aq:pending:" + counterSuffix;
1289              }
1290          }
1291      }
1292  

在ViewRootImpl 的 setView() 方法里

  1. 执行 requestLayout() 方法完成 view 的绘制流程。
  2. 通过 WindowSession 将 View 和 InputChannel 添加到 WMS 中,从而将 View添加到Window 上并且接收触摸事件,这是一次IPC过程。

我们看看这个IPC 过程

res = mWindowSession.addToDisplayAsUser(mWindow, mWindowAttributes,
1156                              getHostVisibility(), mDisplay.getDisplayId(), userId,
1157                              mInsetsController.getRequestedVisibility(), inputChannel, mTempInsets,
1158                              mTempControls);

mWindowSession : 类型是 interface IWindowSession

 public static IWindowSession getWindowSession() {
206          synchronized (WindowManagerGlobal.class) {
207              if (sWindowSession == null) {
208                  try {
209                      // Emulate the legacy behavior.  The global instance of InputMethodManager
210                      // was instantiated here.
211                      // TODO(b/116157766): Remove this hack after cleaning up @UnsupportedAppUsage
212                      InputMethodManager.ensureDefaultInstanceForDefaultDisplayIfNecessary();
213                      IWindowManager windowManager = getWindowManagerService();
214                      sWindowSession = windowManager.openSession(
215                              new IWindowSessionCallback.Stub() {
216                                  @Override
217                                  public void onAnimatorScaleChanged(float scale) {
218                                      ValueAnimator.setDurationScale(scale);
219                                  }
220                              });
221                  } catch (RemoteException e) {
222                      throw e.rethrowFromSystemServer();
223                  }
224              }
225              return sWindowSession;
226          }
227      }

我们看到了 getWindowManagerService();获取了 WMS , 那么再看下 windowManager.openSession 返回值就是 sWindowSession