Activity 创建及窗口显示过程分析,源码基于 android-12.1.0_r4;
在 APP 启动流程分析 中得知,启动 APP 的 Activity 最后会调用到 ActivityTaskSupervisor.realStartActivityLocked()
,最终在 ActivityThread 中先后调用了 handleLaunchActivity() -> performLaunchActivity()
和 handleResumeActivity() -> performResumeActivity()
,
performLaunchActivity():作用是在 Instrumentation.newActivity()
函数中根据 Activity 的类名通过通过反射机制创建对应的 Activity,然后通过 Instrumentation.callActivityOnCreate() -> Activity.performCreate() -> Activity.onCreate()
调用 Activity 的 onCreate () 函数;
performResumeActivity():通过 Activity.performResume() -> Instrumentation.callActivityOnResume() -> Activity.onResume()
调用 Activity 的 onResume() 函数;
但是 handleResumeActivity()
除了调用 performResumeActivity()
之外,还有其他重要工作,接下来开始分析;
1 handleResumeActivity() 分析 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 public void handleResumeActivity (ActivityClientRecord r, boolean finalStateRequest, boolean isForward, String reason) { ... if (!performResumeActivity(r, finalStateRequest, reason)) { return ; } ... final Activity a = r.activity; ... if (r.window == null && !a.mFinished && willBeVisible) { r.window = r.activity.getWindow(); View decor = r.window.getDecorView(); decor.setVisibility(View.INVISIBLE); ViewManager wm = a.getWindowManager(); WindowManager.LayoutParams l = r.window.getAttributes(); a.mDecor = decor; ... if (a.mVisibleFromClient) { if (!a.mWindowAdded) { a.mWindowAdded = true ; wm.addView(decor, l); } else { ... Looper.myQueue().addIdleHandler(new Idler ()); } private WindowManager mWindowManager; public WindowManager getWindowManager () { return mWindowManager; }
主要工作有 3 个:
window.getDecorView():出现了一个 Window 对象,通过 window.getDecorView 获取一个 View 对象 decor,其实是一个 DecorView ,我们知道在 onCreate() 中会 setContentView(),是把一个 View 添加到 mContentParent,而 mContentParent 是 DecorView[PhoneWindow.mDecor] 的一部分;
getWindowManager():返回一个 WindowManager 对象(继承自 ViewManager),实际上是 WindowManagerImpl 对象;
addView():把上面获取的 decor 对象添加到 ViewManager 中,实际上调用的是 WindowManagerImpl.addView();
Window、WindowManager、DecorView 是什么?我们回到 ActivityThread.performLaunchActivity()
;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 private Activity performLaunchActivity (ActivityClientRecord r, Intent customIntent) { ActivityInfo aInfo = r.activityInfo; ... ContextImpl appContext = createBaseContextForActivity(r); Activity activity = null ; try { java.lang.ClassLoader cl = appContext.getClassLoader(); activity = mInstrumentation.newActivity( cl, component.getClassName(), r.intent); ... try { Application app = r.packageInfo.makeApplication(false , mInstrumentation); ... Window window = null ; if (r.mPendingRemoveWindow != null && r.mPreserveWindow) { window = r.mPendingRemoveWindow; r.mPendingRemoveWindow = null ; r.mPendingRemoveWindowManager = null ; } ... activity.attach(appContext, this , getInstrumentation(), r.token, r.ident, app, r.intent, r.activityInfo, title, r.parent, r.embeddedID, r.lastNonConfigurationInstances, config, r.referrer, r.voiceInteractor, window, r.configCallback, r.assistToken, r.shareableActivityToken); ... synchronized (mResourcesManager) { mActivities.put(r.token, r); }... mInstrumentation.callActivityOnCreate(activity, r.state); } ... return activity;
主要工作:
创建 Activity 对应的 ContextImpl 对象;
获取应用所使用的 ClassLoader 对象,用于创建 Activity 对象;
调用 Instrumentation.newActivity() 通过反射机制创建 Activity 对象;
调用 Activity.attach() 方法 ;
通过 Instrumentation.callActivityOnCreate() 调用 Activity.onCreate() 方法;
将当前 Activity 所对应的 ActivityClientRecord 对象添加到 mActivities 数组;
其他流程在 APP 启动流程分析 中已经分析过了,这里重点看一下 attach()
函数;
1.1.1 attach() 1.1.1.1 Window 创建 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 private Window mWindow; final void attach (...) { attachBaseContext(context); mFragments.attachHost(null ); mWindow = new PhoneWindow (this , window, activityConfigCallback); mWindow.setWindowControllerCallback(mWindowControllerCallback); mWindow.setCallback(this ); mWindow.setOnWindowDismissedCallback(this ); mWindow.getLayoutInflater().setPrivateFactory(this ); ... mWindow.setWindowManager( (WindowManager)context.getSystemService(Context.WINDOW_SERVICE), mToken, mComponent.flattenToString(), (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0 ); if (mParent != null ) { mWindow.setContainer(mParent.getWindow()); } mWindowManager = mWindow.getWindowManager(); ...
可以看到这个 Window 其实是一个 PhoneWindow 对象,是 Activity 的一个成员变量,即 Activity.mWindow 是一个 PhoneWindow 对象 ,继续看 setWindowManager()
;
1.1.1.2 WindowManager 创建 1 2 3 4 5 6 7 8 9 10 11 12 13 14 public class PhoneWindow extends Window implements MenuBuilder .Callback { private WindowManager mWindowManager; public void setWindowManager (WindowManager wm, IBinder appToken, String appName, boolean hardwareAccelerated) { mAppToken = appToken; mAppName = appName; mHardwareAccelerated = hardwareAccelerated; if (wm == null ) { wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE); } mWindowManager = ((WindowManagerImpl)wm).createLocalWindowManager(this ); }
PhoneWindow 继承自 Window,setWindowManager()
是在父类 Window 中定义的,又继续调用 WindowManagerImpl.createLocalWindowManager()
:
1 2 3 4 public WindowManagerImpl createLocalWindowManager (Window parentWindow) { return new WindowManagerImpl (mContext, parentWindow, mWindowContextToken); }
所以 Window.mWindowManager 其实是一个 WindowManagerImpl 对象 ;
1.1.2 setContentView() performLaunchActivity()
的最后调用 callActivityOnCreate()
启动了 Activity 的子类的 onCreate()
,我们都知道在其中会调用 setContentView()
,Activity 中有 3 个 setContentView() 方法,选取其中一个:
1 2 3 4 5 public void setContentView (View view) { getWindow().setContentView(view); initWindowDecorActionBar(); }
先来看一下 getWindow()
返回什么:
1 2 3 4 5 6 7 private Window mWindow; public Window getWindow () { return mWindow; } public abstract class Window {
返回了一个 Window 对象,属于 Activity ,通过分析 performLaunchActivity()
得知 getWindow()
返回的是一个 PhoneWindow 对象,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 ViewGroup mContentParent; public void setContentView (View view) { setContentView(view, new ViewGroup .LayoutParams(MATCH_PARENT, MATCH_PARENT)); } public void setContentView (View view, ViewGroup.LayoutParams params) { if (mContentParent == null ) { installDecor(); } else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {} ... if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) { } else { mLayoutInflater.inflate(layoutResID, mContentParent); } mContentParent.addView(view, params); mContentParent.requestApplyInsets(); final Callback cb = getCallback(); if (cb != null && !isDestroyed()) { cb.onContentChanged(); } mContentParentExplicitlySet = true ; }
mContentParent 是一个 ViewGroup,继承自 View,从名字可知它除了是一个 View,还是一个 Group,里面包含了其他 View,上面代码主要有 2 个工作:
installDecor():创建 DecorView[PhoneWindow.mDecor],加载布局到 DecorView,获取 mContentParent;
使用 LayoutInflater 工具解析并生成视图;
addView():把传入的 view 添加到 mContentParent 这个 ViewGroup 中;
先来看一下 installDecor();
1.1.2.1 installDecor() -安装 DecorView 1 2 3 4 5 6 7 8 9 10 11 12 13 14 private DecorView mDecor; private void installDecor () { mForceDecorInstall = false ; if (mDecor == null ) { mDecor = generateDecor(-1 ); ... } else { mDecor.setWindow(this ); } if (mContentParent == null ) { mContentParent = generateLayout(mDecor); ... mTitleView = findViewById(R.id.title);
首先通过 generateDecor()
创建 DecorView ,它是 Activity 的根视图,并把 PhoneWindow 对象传递给 DecorView;
然后通过 generateLayout()
加载布局文件到 DecorView 中,从 DecorView 中获取并返回 mContentParent ,比如 LinearLayout/RelativeLayout/FrameLayout 等,是 DecorView 的子视图;
先来看一下创建 DecorView;
a. generateDecor() - 创建 DecorView 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 protected DecorView generateDecor (int featureId) { Context context; ... return new DecorView (context, featureId, this , getAttributes()); } private PhoneWindow mWindow; DecorView(Context context, int featureId, PhoneWindow window, WindowManager.LayoutParams params) { super (context); ... setWindow(window); } void setWindow (PhoneWindow phoneWindow) { mWindow = phoneWindow; ...
创建 DecorView ,并通过 setWindow()
把 PhoneWindow 对象传递给 DecorView.mWindow ,如果已经存在 DecorView,则直接通过 setWindow()
把 PhoneWindow 传递过去, 这里虽然创建了 DecorView,但是此时的 DecorView 还是一个空白的 FrameLayout (DecorView 继承自 FrameLayout);
继续看 generateLayout()
获取 ViewGropu 对象;
b. generateLayout() - 加载布局到 DecorView 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 protected ViewGroup generateLayout (DecorView decor) { TypedArray a = getWindowStyle(); if (a.getBoolean(R.styleable.XXX, false )) { requestFeature(XXX); int layoutResource; int features = getLocalFeatures(); if ((features & ((1 << FEATURE_LEFT_ICON) | (1 << FEATURE_RIGHT_ICON))) != 0 ) { if (mIsFloating) { TypedValue res = new TypedValue (); getContext().getTheme().resolveAttribute( R.attr.dialogTitleIconsDecorLayout, res, true ); layoutResource = res.resourceId; } else { layoutResource = R.layout.screen_title_icons; } removeFeature(FEATURE_ACTION_BAR); }... else { layoutResource = R.layout.screen_simple; } mDecor.startChanging(); mDecor.onResourcesLoaded(mLayoutInflater, layoutResource); ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT); mDecor.finishChanging(); return contentParent;
从主题文件获取样式信息,根据样式信息调用 requestFeature();
通过 getLocalFeatures()
获取 requestFeature() 的功能;
根据功能获取对应的资源 ID,然后调用 onResourcesLoaded()
根据样式加载对应的布局到 PhoneWindow.mDecor(DecorView) 中;
最后从 DecorView 中通过 findViewById()
获取并返回 id 为 R.id.content
的 View (contentParent )给到 PhoneWindow.mContentParent
;
看一下默认布局:frameworks/base/core/res/res/layout/screen_simple.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 <LinearLayout xmlns:android ="http://schemas.android.com/apk/res/android" android:layout_width ="match_parent" android:layout_height ="match_parent" android:fitsSystemWindows ="true" android:orientation ="vertical" > <ViewStub android:id ="@+id/action_mode_bar_stub" android:inflatedId ="@+id/action_mode_bar" android:layout ="@layout/action_mode_bar" android:layout_width ="match_parent" android:layout_height ="wrap_content" android:theme ="?attr/actionBarTheme" /> <FrameLayout android:id ="@android:id/content" android:layout_width ="match_parent" android:layout_height ="match_parent" android:foregroundInsidePadding ="false" android:foregroundGravity ="fill_horizontal|top" android:foreground ="?android:attr/windowContentOverlay" /> </LinearLayout >
onResourcesLoaded() 分析:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 private DecorCaptionView mDecorCaptionView; void onResourcesLoaded (LayoutInflater inflater, int layoutResource) { ... mDecorCaptionView = createDecorCaptionView(inflater); final View root = inflater.inflate(layoutResource, null ); if (mDecorCaptionView != null ) { if (mDecorCaptionView.getParent() == null ) { addView(mDecorCaptionView, new ViewGroup .LayoutParams(MATCH_PARENT, MATCH_PARENT)); } mDecorCaptionView.addView(root, new ViewGroup .MarginLayoutParams(MATCH_PARENT, MATCH_PARENT)); } else { addView(root, 0 , new ViewGroup .LayoutParams(MATCH_PARENT, MATCH_PARENT)); } mContentRoot = (ViewGroup) root; initializeElevation(); }
DecorCaptionView 的注释意思是 DecorCaptionView 是窗口的标题视图,包含标题和窗口控制按钮,这种 decor 的可见性取决于工作空间和窗口类型,如果窗口类型不需要这样的视图,则 mDecorCaptionView 可能为空,所以要进行判空操作;
可以看到 onResuourcesLoaded()
的目的是加载传入的 layoutResource 成为根视图,然后把根视图添加到 DecorView 中;
接下来看一下 findViewById()
;
1 2 3 4 5 6 7 8 9 10 11 public <T extends View > T findViewById (@IdRes int id) { return getDecorView().findViewById(id); } public final @NonNull View getDecorView () { if (mDecor == null || mForceDecorInstall) { installDecor(); } return mDecor; }
可见 findViewById()
都是从 DecorView 中查找 View,所以返回的 contentParent 是 DecorView 的一部分,即 mContentParent 是 DecorView 的一部分 ;
1.1.2.2 ContentParent.addView - 添加 view 到 ContentParent installDecor()
创建 DecorView、加载布局到 DecorView,获取 ContentParent 后,下一步就是调用 ContentParent.addView()
把 View 添加到 mContentParent 这个 ViewGroup 中;
1 2 3 4 5 6 7 8 9 10 11 12 13 public void addView (View child, int index) { ... LayoutParams params = child.getLayoutParams(); ... addView(child, index, params); } public void addView (View child, int index, LayoutParams params) { ... requestLayout(); invalidate(true ); addViewInner(child, index, params, false ); }
这里就不详细分析了,继续回到 handleResumeActivity()
中;
2 WMI.addView(DecorView) 先回忆一下为什么分析 setContentView(),因为在分析 handleResumeActivity()
时遇到了 DecorView、Window、WindowManager 等不熟悉的对象,但是这些对象的来源和 setContentView()
有关,所以就转而分析 setContentView()
了;
1 2 3 4 5 6 7 8 9 10 public void handleResumeActivity (ActivityClientRecord r, boolean finalStateRequest, boolean isForward, String reason) { ... ViewManager wm = a.getWindowManager(); wm.addView(decor, l); } else { ... Looper.myQueue().addIdleHandler(new Idler ()); }
上文得知 wm 是 WindowManagerImpl 实例,所以继续调用到 WindowManagerImpl.addView()
;
1 2 3 4 5 6 7 private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance(); public void addView (@NonNull View view, @NonNull ViewGroup.LayoutParams params) { applyTokens(params); mGlobal.addView(view, params, mContext.getDisplayNoVerify(), mParentWindow, mContext.getUserId()); }
WindowManagerImpl 又直接交给了 WindowManagerGlobal 处理,这个 mGlobal
是一个单例;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 private final ArrayList<View> mViews = new ArrayList <View>(); private final ArrayList<ViewRootImpl> mRoots = new ArrayList <ViewRootImpl>(); private final ArrayList<WindowManager.LayoutParams> mParams = new ArrayList <WindowManager.LayoutParams>(); public void addView (View view, ViewGroup.LayoutParams params, Display display, Window parentWindow, int userId) { ... ViewRootImpl root; View panelParentView = null ; synchronized (mLock) { ... root = new ViewRootImpl (view.getContext(), display); view.setLayoutParams(wparams); mViews.add(view); mRoots.add(root); mParams.add(wparams); try { root.setView(view, wparams, panelParentView, userId); } catch (RuntimeException e) { ...
new 了一个 ViewRootImpl 对象,然后调用 VRI.setView(),来看看 ViewRootImpl 的构造函数;
2.1 ViewRootImpl 构造函数 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 @SuppressWarnings({"EmptyCatchBlock", "PointlessBooleanExpression"}) public final class ViewRootImpl implements ViewParent ...{ public ViewRootImpl (Context context, Display display) { this (context, display, WindowManagerGlobal.getWindowSession(), false ); } public ViewRootImpl (@UiContext Context context, Display display, IWindowSession session, boolean useSfChoreographer) { mContext = context; mWindowSession = session; mDisplay = display; mBasePackageName = context.getBasePackageName(); mThread = Thread.currentThread(); ... mWidth = -1 ; mHeight = -1 ; ... mWindow = new W (this ); mAttachInfo = new View .AttachInfo(mWindowSession, mWindow, display, this , mHandler, this , context); ... mChoreographer = useSfChoreographer ? Choreographer.getSfInstance() : Choreographer.getInstance(); mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE); mInsetsController = new InsetsController (new ViewRootInsetsControllerHost (this )); ...
从注释中看出 ViewRootImpl 是 View 中的顶级层级,实现了 View 和 WindowManager 之间需要的协议;
构造函数传递了一个 WindowManagerGlobal.getWindowSession()
作为参数,创建了 AttachInfo 对象,AttachInfo 是 View 的内部类,其中有个 mViewRootImpl 属性,构造 AttachInfo 的时候把 ViewRootImpl 作为参数传递给了 mViewRootImpl,这样就把 View 和 ViewRootImpl 绑定起来了,然后 PhoneWindow.getViewRootImpl 获取的也是 AttachInfo.mViewRootImpl;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 private static IWindowSession sWindowSession; public static IWindowSession getWindowSession () { synchronized (WindowManagerGlobal.class) { if (sWindowSession == null ) { try { InputMethodManager.ensureDefaultInstanceForDefaultDisplayIfNecessary(); IWindowManager windowManager = getWindowManagerService(); sWindowSession = windowManager.openSession( new IWindowSessionCallback .Stub() { @Override public void onAnimatorScaleChanged (float scale) { ValueAnimator.setDurationScale(scale); } }); ... return sWindowSession; public static IWindowManager getWindowManagerService () { synchronized (WindowManagerGlobal.class) { if (sWindowManagerService == null ) { sWindowManagerService = IWindowManager.Stub.asInterface( ServiceManager.getService("window" )); ... return sWindowManagerService;
getWindowManagerService()
获取 WMS 的 binder 代理 sWindowManagerService,所以 openSession()
的实现在 WMS 中:
1 2 3 4 5 6 7 8 public IWindowSession openSession (IWindowSessionCallback callback) { return new Session (this , callback); } class Session extends IWindowSession .Stub implements IBinder .DeathRecipient { public Session (WindowManagerService service, IWindowSessionCallback callback) { mService = service;
总结 ViewRootImpl 构造函数:
ViewRootImpl 通过 WindowManagerGlobal.getWindowSession()
先通过 binder 通信 获取 WMS 的代理 ;
调用 WMS.openSession() 得到一个 IWindowSession 对象(Session 继承自 IWindowSession.Stub),支持 Binder 通信,且属于服务端;
把 IWindowSession 传递给 ViewRootImpl.mWindowSession
,Session 持有 WMS 对象,这样 Activity 就可以通过 mWindowSession 和 WMS 通信 (为什么不直接使用 WMS 的代理通信呢?);
创建 W 对象,W 继承 IWindow.Stub,会通过 ViewRootImpl.setView()
传递到 WMS 中以创建 Activity 对应的 WindowState,W 也负责 WMS 到 Activity 的通信 ;
2.2 ViewRootImpl.setView() 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 public void setView (View view, WindowManager.LayoutParams attrs, View panelParentView, int userId) { synchronized (this ) { if (mView == null ) { mView = view; ... requestLayout(); ... try { ... res = mWindowSession.addToDisplayAsUser(mWindow, mWindowAttributes, getHostVisibility(), mDisplay.getDisplayId(), userId, mInsetsController.getRequestedVisibilities(), inputChannel, mTempInsets, mTempControls); ... view.assignParent(this );
传入的参数 view 就是 DecorView,保存到 ViewRootImpl.mView;
requestLayout():Activity 视图首次显示之前,完成第一次 layout 布局过程,以确保在收到任何系统事件后面重新布局,最终调用 performTraversals() 那套 measure/layout/draw 流程;
addToDisplayAsUser():完成 WindowManager 和 WMS 的通信,将 Window 信息传递给 WMS;
2.2.1 VRI.requestLayout() - 请求布局 1 2 3 4 5 6 7 8 9 10 11 12 13 14 public void requestLayout () { if (!mHandlingLayoutInLayoutRequest) { checkThread(); mLayoutRequested = true ; scheduleTraversals(); } } void checkThread () { if (mThread != Thread.currentThread()) { throw new CalledFromWrongThreadException ( "Only the original thread that created a view hierarchy can touch its views." ); } }
有个 checkThread() 函数,从前面 ViewRootImpl 构造函数可知这里的 mThread 是创建 ViewRootImpl 的线程,所以这里判断当前线程和创建 ViewRootImpl 的线程是否是同一线程,如果不是,则抛出异常提示只有创建它的线程才能更新它的 View,所以通常说的子线程不能更新 UI 就是这个原因,但是在 ViewRootImpl 创建出来之前 UI 的更新没有线程限制,因为 checkThread() 不会被执行 ;
1 2 3 4 5 6 7 8 9 10 11 12 13 final TraversalRunnable mTraversalRunnable = new TraversalRunnable (); void scheduleTraversals () { if (!mTraversalScheduled) { mTraversalScheduled = true ; mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier(); mChoreographer.postCallback( Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null ); notifyRendererOfFramePending(); pokeDrawLockIfNeeded(); } }
主要工作:
发送同步消息屏障,保障异步消息优先执行,后续会对消息添加异步标志;
向 Choreographer 注册一个 VSYNC 信号回调处理,以执行视图的 Traversal 相关逻辑;
当回调时,会执行类型为 TraversalRunnable 的 run() 方法;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 public void postCallback (int callbackType, Runnable action, Object token) { postCallbackDelayed(callbackType, action, token, 0 ); } public void postCallbackDelayed (int callbackType, Runnable action, Object token, long delayMillis) { ... postCallbackDelayedInternal(callbackType, action, token, delayMillis); } private void postCallbackDelayedInternal (int callbackType, Object action, Object token, long delayMillis) { ... synchronized (mLock) { final long now = SystemClock.uptimeMillis(); final long dueTime = now + delayMillis; mCallbackQueues[callbackType].addCallbackLocked(dueTime, action, token); if (dueTime <= now) { scheduleFrameLocked(now); } else { Message msg = mHandler.obtainMessage(MSG_DO_SCHEDULE_CALLBACK, action); msg.arg1 = callbackType; msg.setAsynchronous(true ); mHandler.sendMessageAtTime(msg, dueTime); } } }
根据传入的 Runnable 构建 CallbackRecord 对象:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 public void addCallbackLocked (long dueTime, Object action, Object token) { CallbackRecord callback = obtainCallbackLocked(dueTime, action, token); CallbackRecord entry = mHead; if (entry == null ) { mHead = callback; return ; } if (dueTime < entry.dueTime) { callback.next = entry; mHead = callback; return ; } while (entry.next != null ) { if (dueTime < entry.next.dueTime) { callback.next = entry.next; break ; } entry = entry.next; } entry.next = callback; }
最终都是执行到 scheduleFrameLocked()
;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 private void scheduleFrameLocked (long now) { if (!mFrameScheduled) { mFrameScheduled = true ; if (USE_VSYNC) { if (DEBUG_FRAMES) { Log.d(TAG, "Scheduling next frame on vsync." ); } if (isRunningOnLooperThreadLocked()) { scheduleVsyncLocked(); } else { Message msg = mHandler.obtainMessage(MSG_DO_SCHEDULE_VSYNC); msg.setAsynchronous(true ); mHandler.sendMessageAtFrontOfQueue(msg); } } else { final long nextFrameTime = Math.max( mLastFrameTimeNanos / TimeUtils.NANOS_PER_MS + sFrameDelay, now); if (DEBUG_FRAMES) { Log.d(TAG, "Scheduling next frame in " + (nextFrameTime - now) + " ms." ); } Message msg = mHandler.obtainMessage(MSG_DO_FRAME); msg.setAsynchronous(true ); mHandler.sendMessageAtTime(msg, nextFrameTime); } } } private final class FrameHandler extends Handler { public FrameHandler (Looper looper) { super (looper); } @Override public void handleMessage (Message msg) { switch (msg.what) { case MSG_DO_FRAME: doFrame(System.nanoTime(), 0 , new DisplayEventReceiver .VsyncEventData()); break ; case MSG_DO_SCHEDULE_VSYNC: doScheduleVsync(); break ; case MSG_DO_SCHEDULE_CALLBACK: doScheduleCallback(msg.arg1); break ; } } }
1 2 3 4 5 6 7 8 9 void doFrame (long frameTimeNanos, int frame, DisplayEventReceiver.VsyncEventData vsyncEventData) { doCallbacks(Choreographer.CALLBACK_INPUT, frameTimeNanos, frameIntervalNanos); doCallbacks(Choreographer.CALLBACK_ANIMATION, frameTimeNanos, frameIntervalNanos); doCallbacks(Choreographer.CALLBACK_INSETS_ANIMATION, frameTimeNanos, frameIntervalNanos); doCallbacks(Choreographer.CALLBACK_TRAVERSAL, frameTimeNanos, frameIntervalNanos); doCallbacks(Choreographer.CALLBACK_COMMIT, frameTimeNanos, frameIntervalNanos);
按照顺序执行几种类型的事件回调,这里我们要分析的是 CALLBACK_TRAVERSAL 类型,在 scheduleTraversals()
中传入;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 void doCallbacks (int callbackType, long frameTimeNanos, long frameIntervalNanos) { CallbackRecord callbacks; synchronized (mLock) { try { Trace.traceBegin(Trace.TRACE_TAG_VIEW, CALLBACK_TRACE_TITLES[callbackType]); for (CallbackRecord c = callbacks; c != null ; c = c.next) { if (DEBUG_FRAMES) { Log.d(TAG, "RunCallback: type=" + callbackType + ", action=" + c.action + ", token=" + c.token + ", latencyMillis=" + (SystemClock.uptimeMillis() - c.dueTime)); } c.run(frameTimeNanos); } } private static final class CallbackRecord { public CallbackRecord next; public long dueTime; public Object action; public Object token; @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public void run (long frameTimeNanos) { if (token == FRAME_CALLBACK_TOKEN) { ((FrameCallback)action).doFrame(frameTimeNanos); } else { ((Runnable)action).run(); } } }
CallbackRecord.run()
直接运行封装的 Runnable.run()
,而 scheduleTraversals()
中传入的 Runnable 是 TraversalRunnable,所以这里回调执行到 TraversalRunnable.run()
;
1 2 3 4 5 6 7 8 final class TraversalRunnable implements Runnable { @Override public void run () { doTraversal(); } } final TraversalRunnable mTraversalRunnable = new TraversalRunnable ();
调用 doTraversal()
;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 void doTraversal () { if (mTraversalScheduled) { mTraversalScheduled = false ; mHandler.getLooper().getQueue().removeSyncBarrier(mTraversalBarrier); if (mProfile) { Debug.startMethodTracing("ViewAncestor" ); } performTraversals(); if (mProfile) { Debug.stopMethodTracing(); mProfile = false ; } } }
做了两件事:
移除同步消息屏障;
调用 performTraversals()
;
1 2 private void performTraversals () {
performTraversals()
方法向 WMS 申请了 Surface、测量(measure)、布局(layout)、绘制(draw)三大流程,此文暂不分析;参考
2.2.2 Session.addToDisplayAsUser() 1 2 3 4 5 6 7 8 9 final WindowManagerService mService; public int addToDisplayAsUser (IWindow window, WindowManager.LayoutParams attrs, int viewVisibility, int displayId, int userId, InsetsVisibilities requestedVisibilities, InputChannel outInputChannel, InsetsState outInsetsState, InsetsSourceControl[] outActiveControls) { return mService.addWindow(this , window, attrs, viewVisibility, displayId, userId, requestedVisibilities, outInputChannel, outInsetsState, outActiveControls); }
mService 是 WMS 对象,直接调用 WMS.addWindow()
;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 final HashMap<IBinder, WindowState> mWindowMap = new HashMap <>(); public int addWindow (Session session, IWindow client, ...) { ... WindowState parentWindow = null ; final int callingUid = Binder.getCallingUid(); final int callingPid = Binder.getCallingPid(); final long origId = Binder.clearCallingIdentity(); final int type = attrs.type; synchronized (mGlobalLock) { ... if (type >= FIRST_SUB_WINDOW && type <= LAST_SUB_WINDOW) { parentWindow = windowForClientLocked(null , attrs.token, false ); ... } ... ActivityRecord activity = null ; final boolean hasParent = parentWindow != null ; WindowToken token = displayContent.getWindowToken( hasParent ? parentWindow.mAttrs.token : attrs.token); ... final WindowState win = new WindowState (this , session, client, token, parentWindow, appOp[0 ], attrs, viewVisibility, session.mUid, userId, session.mCanAddInternalSystemWindow); ... win.attach(); mWindowMap.put(client.asBinder(), win); ... return res; }
主要工作:
创建 WindowState 对象,用来描述与 W 对象所关联的 Activity 的窗口状态,并且以后会通过这个 W 对象来控制对应的 Activity 的窗口状态;
调用 WindowState.attach() ;
1 2 3 4 5 final Session mSession; void attach () { mSession.windowAddedLocked(); }
继续调用 Session.windowAddedLocked()
;
1 2 3 4 5 6 7 8 9 10 11 SurfaceSession mSurfaceSession; void windowAddedLocked () { ... if (mSurfaceSession == null ) { mSurfaceSession = new SurfaceSession (); mService.mSessions.add(this ); ... } mNumWindow++; }
3 总结
每个 Activity 中有个 Window 对象,用来描述程序窗口,每个窗口又包含一个 View 对象,用来描述程序视图;
performLaunchActivity() 时通过 attach() 方法生成 PhoneWindow 对象,生成 WindowManager(其实为 WindowManagerImpl 对象)并和 mWindow 绑定 ,在 onCreate() 中会 调用 PhoneWindow.setContentView(),
在 setContentView()
创建了 DecorView ,并关联了 PhoneWindow 对象(PhoneWindow 和 DecorView 互相持有);
然后根据主题获取样式信息,根据样式加载对应的布局到 DecorView;
再从 DecorView 中通过 findViewById()
获取并返回 id 为 R.id.content
的 View (contentParent )给到 PhoneWindow.mContentParent
;
最后把 setContentView() 传入的 View 添加到 PhoneWindow.mContentParent,只是把需要添加的 View添加保存在了 DecorView 中,但是还没绘制;
在 performResumeActivity() 阶段通过 WindowManager.addView() 把 DecorView 添加到 Window 里,真正干活的是 WindowManagerGlobal,在其中创建了 ViewRootImpl,VRI 包含了 mWindowSession:Session 对象用于 Activity 向 WMS 通信,也包含了 mWindow:W 对象用于 WMS 向 Activity 通信,然后通过 setView() 实现 addView(),把视图交给 WindowManager 管理,
在其中通过 requestLayout() 触发第一次绘制,向 WMS 申请 Surface;
然后再通过 WMS.addWindow() 在 WMS 中创建一个与 Window 相关的 WindowState 对象,WMS 管理所有的 Window 的层级、位置、大小,掌管 Surface 的显示顺序、位置、大小,应用端在分配的 Surface 绘制完成后,SurfaceFlinger 把这些 Surface 图像按 WMS 中的层级、位置、大小等进行合成,最终写屏幕的缓冲区显示出来;
AMS、Activity、WMS建立连接的过程如下:
Activity 启动时,AMS 服务会在服务端创建一个 ActivityRecord 对象;
AMS 使用 ActivityRecord(实现接口 IApplicationToken)为参数请求 WMS,WMS 为 Activity 组件创建一个 AppWindowToken 对象,ActivityRecord 对象被保存在 AppWindowToken 对象的成员变量 appToken 中;
于是在启动完成该 Activity 组件后,WMS 获得了一个 ActivityRecord 对象和一个对应的 W 对象;
WMS 会根据 AppWindowToken 对象以及 W 对象,为 Activity 创建一个 WindowState 对象,并且将 AppWindowToken 对象保存在 WindowState 对象的mAppToken中;
每一个 Activity 组件,在 ActivityManagerService 服务内部都有一个对应的 ActivityRecord 对象,并且在 WindowManagerService 服务内部关联有一个AppWindowToken 对象;