参考连接: www.jianshu.com/p/b3a1ea792…
1. Window 加载视图过程
1. 了解整体视图关系
Activity: 本身不是窗口,也不是视图,只是窗口的载体,一方面是 key, touch 事件的响应处理,一方面是对界面生命周期做统一调度。
Window: 一个顶级窗口查看和行为的一个抽象基类,也是装载View 的原始容器,处理一些应用窗口通用的逻辑。使用时到的是它的唯一实现类: PhoneWindow 。 Window 受 WindowManager 统一管理。
DecorView: 顶级视图,一般情况下它内部会包含一个竖直方向的LinearLayout ,上面的标题栏(titleBar),下面是内容栏。通常我们在 Activity 中通过 setContentView 所设置的布局文件就是被加载到 id 为 android.R.id.content 的内容栏里(FrameLayout)。
2. Window 的类型
添加窗口是通过 WindowManagerGlobal 的 addView 方法操作的,有三个必要参数:
- view : 表示要显示的 View, 一般是对该 view 的上下文进行操作。(view.getContext())
- display : 表示要输出的显示设备
- 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 的创建
对于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
下面看看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() 方法里
- 执行 requestLayout() 方法完成 view 的绘制流程。
- 通过 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