目录
2.1 Activity、PhoneWindow、DecorView、ViewRootImpl、Choreographer、Surface的创建和关系
2.1.1 Activity 创建:APP拥有Activity
2.1.2 Window的创建:Activity拥有Window
2.1.3 DecorView的创建:Window拥有DecorView
2.1.4 ViewRootImpl的创建:DecorView拥有ViewRootImpl
2.1.5 Surface的创建:ViewRootImpl拥有Surface
2.1.6 Choreographer的创建:ViewRootImpl拥有Choreographer
2.1.7 Activity、PhoneWindow(Window)、DecorView、ViewRootImpl和Surface之间的关系说明什么
1 相关概念介绍
说到显示系统,或者我们平时做流畅性时候,常常可以碰到如下的一些关键字。本文希望通过对一些流程的简单介绍,把这些概念串联起来,看看App,system_sever(这里主要是wms),surfaceflinger之间是如何协同工作的

- View: 视图,绘制到屏幕上的内容,如 TextView, ImageView 等。
- Window: View 的载体,对 Window 进行添加和删除需要通过 WindowManager 来操作。Window 并不是真实存在的,View 才是 Android 中的视图呈现形式,View 不能单独存在,它必须依附在 Window 这个抽象的概念上面。
- WindowManager: 管理系统中的 Window, 实际功能通过 Binder IPC 借由 WindowManagerService 实现。
- Surface: 一个 Window 对应一个 Surface(当存在 SurfaceView 则例外)。Surface 内部持有一个 BufferQueueProducer 指针(在 Layer 中创建)可以生产图像缓存区用来绘图,与 App 和 SurfaceFlinger 形成一个生产者消费者模型。
- Layer: App 请求创建 Surface 时 SurfaceFlinger 会创建 Layer 对象,它是 SurfaceFlinger 合成的基本操作单元,一个 Surface 对应一个 Layer
- SurfaceView: 一种比TextView, imageview特殊的 View, 它不与其宿主的 Window 共享一个 Surface, 而是有自己的独立 Surface。并且它可以在一个独立的线程中绘制 UI。 SurfaceView 一般用来实现比较复杂界面显示h比较常见的就是视频。
- Choreographer: 编舞者,用来控制当收到 VSync 信号后才开始绘制任务,周期一般是16.6\11.1\8.3ms,它作为一个节拍器在控制应用的绘制
- SurfaceFlinger: 管理消费当前可见的 Surface,所有被渲染的可见 Surface 都被 SurfaceFlinger,通过 WindowManager 提供的信息合成,提交到屏幕的后缓冲区,等待屏幕的下一个Vsync信号到来,再显示到屏幕上。SufaceFlinger 在屏幕和上层之间起到了一个承上启下的作用。
- HWComposer: HardWare Composer, 定义一套 HAL 层接口,芯片厂商根据硬件特点来实现这套接口。其主要工作是将 SurfaceFlinger 计算后的 Layer 显示参数合成到显示器 Buffer 上。当然 SurfaceFlinger 并非是 HWC 的唯一输入源,例如摄像头的预览输入 Buffer 可以由硬件设备直接写入,然后作为 HWC 的输入之一与 SurfaceFlinger 的输出做最后的合
- Gralloc: 图形内存分配器,用来分配图像生产者请求的内存
2.关键概念的关系
2.1 Activity、PhoneWindow、DecorView、ViewRootImpl、Choreographer、Surface的创建和关系

2.1.1 Activity 创建:APP拥有Activity
点击应用图标,会通过Zygote创建一个进程,然后调用调应用的ActivityThread main,最终调用ActivityThread.handleLaunchActivity
1.handleLaunchActivity 调用performLaunchActivity创建一个Actiivty
2.performLaunchActivity调用mInstrumentation.newActivity创建Activity
3.performLaunchActivity还会创建一个进程,作为这些资源的载体
这些都是跑在ActivityThread中的,也就是应用的主线程,到这来就APP就拥有了Activity
/**
* Extended implementation of activity launch. Used when server requests a launch or relaunch.
*/
@Override
public Activity handleLaunchActivity(ActivityClientRecord r,
PendingTransactionActions pendingActions, Intent customIntent) {
// If we are getting ready to gc after going to the background, well
// we are back active so skip it.
unscheduleGcIdler();
mSomeActivitiesChanged = true;
if (r.profilerInfo != null) {
mProfiler.setProfiler(r.profilerInfo);
mProfiler.startProfiling();
}
// Make sure we are running with the most recent config.
handleConfigurationChanged(null, null);
if (localLOGV) Slog.v(
TAG, "Handling launch of " + r);
// Initialize before creating the activity
if (!ThreadedRenderer.sRendererDisabled
&& (r.activityInfo.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0) {
HardwareRenderer.preload();
}
WindowManagerGlobal.initialize();
// Hint the GraphicsEnvironment that an activity is launching on the process.
GraphicsEnvironment.hintActivityLaunch();
//1. 调用performLaunchActivity创建一个Activity
final Activity a = performLaunchActivity(r, customIntent);
if (a != null) {
r.createdConfig = new Configuration(mConfiguration);
reportSizeConfigurations(r);
if (!r.activity.mFinished && pendingActions != null) {
pendingActions.setOldState(r.state);
pendingActions.setRestoreInstanceState(true);
pendingActions.setCallOnPostCreate(true);
}
} else {
// If there was an error, for any reason, tell the activity manager to stop us.
try {
ActivityTaskManager.getService()
.finishActivity(r.token, Activity.RESULT_CANCELED, null,
Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
return a;
}
/** Core implementation of activity launch. */
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
......
Activity activity = null;
try {
java.lang.ClassLoader cl = appContext.getClassLoader();
// 2. 调用mInstrumentation.newActivit创建一个Activity
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
StrictMode.incrementExpectedActivityCount(activity.getClass());
r.intent.setExtrasClassLoader(cl);
r.intent.prepareToEnterProcess();
if (r.state != null) {
r.state.setClassLoader(cl);
}
} catch (Exception e) {
if (!mInstrumentation.onException(activity, e)) {
throw new RuntimeException(
"Unable to instantiate activity " + component
+ ": " + e.toString(), e);
}
}
try {
//3. 创建一个进程
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
......
return activity;
}
2.1.2 Window的创建:Activity拥有Window
接着2.1.1,调用到performLaunchActivity后会创建Actvity和Application,同时还会调用
1. 调用 activity.attach通过该方法创建一个Window
2.由于Window本身是个抽象类,因此在创建的时候会创建它的具体实现类PhoneWindow
到这里Actvity拥有了自己的Window:mWindow
/** Core implementation of activity launch. */
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
......
Activity activity = null;
try {
java.lang.ClassLoader cl = appContext.getClassLoader();
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
StrictMode.incrementExpectedActivityCount(activity.getClass());
r.intent.setExtrasClassLoader(cl);
r.intent.prepareToEnterProcess();
if (r.state != null) {
r.state.setClassLoader(cl);
}
} catch (Exception e) {
if (!mInstrumentation.onException(activity, e)) {
throw new RuntimeException(
"Unable to instantiate activity " + component
+ ": " + e.toString(), e);
}
}
try {
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
......
if (activity != null) {
CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
Configuration config = new Configuration(mCompatConfiguration);
if (r.overrideConfig != null) {
config.updateFrom(r.overrideConfig);
}
if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
+ r.activityInfo.name + " with config " + config);
Window window = null;
if (r.mPendingRemoveWindow != null && r.mPreserveWindow) {
window = r.mPendingRemoveWindow;
r.mPendingRemoveWindow = null;
r.mPendingRemoveWindowManager = null;
}
appContext.setOuterContext(activity);
//1. 调用 activity.attach通过该方法创建一个Window
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)
}
return activity;
}
final void attach(Context context, ActivityThread aThread,
Instrumentation instr, IBinder token, int ident,
Application application, Intent intent, ActivityInfo info,
CharSequence title, Activity parent, String id,
NonConfigurationInstances lastNonConfigurationInstances,
Configuration config, String referrer, IVoiceInteractor voiceInteractor,
Window window, ActivityConfigCallback activityConfigCallback, IBinder assistToken) {
attachBaseContext(context);
mFragments.attachHost(null /*parent*/);
//2.创建一个PhoneWindow
mWindow = new PhoneWindow(this, window, activityConfigCallback);
......
}2.1.3 DecorView的创建:Window拥有DecorView
接着2.1.1和2.1.2,调用到performLaunchActivity后会创建Actvity和Application,创建window,然后还会调用mInstrumentation.callActivityOnCreate,这个最终会调用调应用自己实现的具体Activity类中去,调用的该具体类的Actvity的OnCreate,exp:如下代码中的MainActivity,应用会在这里调用setContentView.
1.Activity的setContentView被调用,在这个函数中会去调用对应PhoneWindow的setContentView
2.Window的setContentView,在这个函数中会通过installDecor来创建为PhoneWindow创建DecorVIew
到这来Window拥有了自己的DecorView:mDecor
//frameworks/base/core/java/android/app/ActivityThread.java
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
......
if (r.isPersistable()) {
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
}
.......
}
// exp:
public class MainActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
}
}
/**
* Set the activity content from a layout resource. The resource will be
* inflated, adding all top-level views to the activity.
*
* @param layoutResID Resource ID to be inflated.
*
* @see #setContentView(android.view.View)
* @see #setContentView(android.view.View, android.view.ViewGroup.LayoutParams)
*/
public void setContentView(@LayoutRes int layoutResID) {
getWindow().setContentView(layoutResID);
initWindowDecorActionBar();
}/frameworks/base/core/java/com/android/internal/policy/PhoneWindow.java
@Override
public void setContentView(View view) {
setContentView(view, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
}
@Override
public void setContentView(View view, ViewGroup.LayoutParams params) {
// Note: FEATURE_CONTENT_TRANSITIONS may be set in the process of installing the window
// decor, when theme attributes and the like are crystalized. Do not check the feature
// before this happens.
if (mContentParent == null) {
//1.调用installDecor创建DecorView
installDecor();
} else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
mContentParent.removeAllViews();
}
if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
view.setLayoutParams(params);
final Scene newScene = new Scene(mContentParent, view);
transitionTo(newScene);
} else {
mContentParent.addView(view, params);
}
mContentParent.requestApplyInsets();
final Callback cb = getCallback();
if (cb != null && !isDestroyed()) {
cb.onContentChanged();
}
mContentParentExplicitlySet = true;
}
private void installDecor() {
mForceDecorInstall = false;
if (mDecor == null) {
//2. 创建DecorView
mDecor = generateDecor(-1);
mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
mDecor.setIsRootNamespace(true);
if (!mInvalidatePanelMenuPosted && mInvalidatePanelMenuFeatures != 0) {
mDecor.postOnAnimation(mInvalidatePanelMenuRunnable);
}
} else {
mDecor.setWindow(this);
}
......
}
2.1.4 ViewRootImpl的创建:DecorView拥有ViewRootImpl
DecorView中的方法很多都是通过getViewRootImpl去调用ViewRootImpl去实现的,DecorView的成员变量中虽然没有保存ViewRootImpl,但是它还是一直持有ViewRootImpl的引用
2.1.5 Surface的创建:ViewRootImpl拥有Surface
在2.1.3中我们看到了,当Activity创建的时候会走到Activity的onCreate这个生命周期函数,同样的当应用到前台的时候,会AMS会通过Binder调用最终调用调handleResumeActivity,最终是在relayoutWindow的时候,ViewRootImpl成员变量mSurface才真正赋值
到这里ViewRootImp,通过copyFrom的方式拥有了自己的Surface

1.handleResumeActivity会通过调用到Actvity的makeVisible
2.调用WindowManagerImpl,addView
3.调用WindowManagerGlobal中的addview
4.调用viewroot的setview
5.requestLayout被调用
6.scheduleTraversals被调用
7. mTraversalRunnable被调用
8. 最终调用到了relayoutWindow
9.到这里mSurface被真正赋值: mSurface.copyFrom(mSurfaceControl)
public void handleResumeActivity(IBinder token, boolean finalStateRequest, boolean isForward,
String reason) {
// The window is now visible if it has been added, we are not
// simply finishing, and we are not starting another activity.
if (!r.activity.mFinished && willBeVisible && r.activity.mDecor != null && !r.hideForNow) {
if (r.newConfig != null) {
performConfigurationChangedForActivity(r, r.newConfig);
if (DEBUG_CONFIGURATION) {
Slog.v(TAG, "Resuming activity " + r.activityInfo.name + " with newConfig "
+ r.activity.mCurrentConfig);
}
r.newConfig = null;
}
if (localLOGV) Slog.v(TAG, "Resuming " + r + " with isForward=" + isForward);
WindowManager.LayoutParams l = r.window.getAttributes();
if ((l.softInputMode
& WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION)
!= forwardBit) {
l.softInputMode = (l.softInputMode
& (~WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION))
| forwardBit;
if (r.activity.mVisibleFromClient) {
ViewManager wm = a.getWindowManager();
View decor = r.window.getDecorView();
wm.updateViewLayout(decor, l);
}
}
r.activity.mVisibleFromServer = true;
mNumVisibleActivities++;
if (r.activity.mVisibleFromClient) {
//1. 调用makeVisible,使得activity可见
r.activity.makeVisible();
}
}
r.nextIdle = mNewActivities;
mNewActivities = r;
if (localLOGV) Slog.v(TAG, "Scheduling idle handler for " + r);
Looper.myQueue().addIdleHandler(new Idler());
}frameworks/base/core/java/android/app/Activity.java
void makeVisible() {
if (!mWindowAdded) {
ViewManager wm = getWindowManager();
//2.调用WindowManagerImpl,addView
wm.addView(mDecor, getWindow().getAttributes());
mWindowAdded = true;
}
mDecor.setVisibility(View.VISIBLE);
} /frameworks/base/core/java/android/view/WindowManagerImpl.java
public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
applyDefaultToken(params);
//3.调用WindowManagerGlobal中的addview
mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow);
}/frameworks/base/core/java/android/view/WindowManagerGlobal.java
public void addView(View view, ViewGroup.LayoutParams params,
Display display, Window parentWindow) {
if (view == null) {
throw new IllegalArgumentException("view must not be null");
}
if (display == null) {
throw new IllegalArgumentException("display must not be null");
}
if (!(params instanceof WindowManager.LayoutParams)) {
throw new IllegalArgumentException("Params must be WindowManager.LayoutParams");
}
final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams) params;
if (parentWindow != null) {
parentWindow.adjustLayoutParamsForSubWindow(wparams);
} else {
// If there's no parent, then hardware acceleration for this view is
// set from the application's hardware acceleration setting.
final Context context = view.getContext();
if (context != null
&& (context.getApplicationInfo().flags
& ApplicationInfo.FLAG_HARDWARE_ACCELERATED) != 0) {
wparams.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
}
}
ViewRootImpl root;
View panelParentView = null;
synchronized (mLock) {
// Start watching for system property changes.
if (mSystemPropertyUpdater == null) {
mSystemPropertyUpdater = new Runnable() {
@Override public void run() {
synchronized (mLock) {
for (int i = mRoots.size() - 1; i >= 0; --i) {
mRoots.get(i).loadSystemProperties();
}
}
}
};
SystemProperties.addChangeCallback(mSystemPropertyUpdater);
}
int index = findViewLocked(view, false);
if (index >= 0) {
if (mDyingViews.contains(view)) {
// Don't wait for MSG_DIE to make it's way through root's queue.
mRoots.get(index).doDie();
} else {
throw new IllegalStateException("View " + view
+ " has already been added to the window manager.");
}
// The previous removeView() had not completed executing. Now it has.
}
// If this is a panel window, then find the window it is being
// attached to for future reference.
if (wparams.type >= WindowManager.LayoutParams.FIRST_SUB_WINDOW &&
wparams.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
final int count = mViews.size();
for (int i = 0; i < count; i++) {
if (mRoots.get(i).mWindow.asBinder() == wparams.token) {
panelParentView = mViews.get(i);
}
}
}
root = new ViewRootImpl(view.getContext(), display);
view.setLayoutParams(wparams);
mViews.add(view);
mRoots.add(root);
mParams.add(wparams);
// do this last because it fires off messages to start doing things
try {
//4.调用viewroot的setview
root.setView(view, wparams, panelParentView);
} catch (RuntimeException e) {
// BadTokenException or InvalidDisplayException, clean up.
if (index >= 0) {
removeViewLocked(index, true);
}
throw e;
}
}
}/frameworks/base/core/java/android/view/ViewRootImpl.java
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
synchronized (this) {
if (mView == null) {
......
mAdded = true;
int res; /* = WindowManagerImpl.ADD_OKAY; */
// Schedule the first layout -before- adding to the window
// manager, to make sure we do the relayout before receiving
// any other events from the system.
//5.requestLayout被调用
requestLayout();
......
}
}
public void requestLayout() {
if (!mHandlingLayoutInLayoutRequest) {
checkThread();
mLayoutRequested = true;
//6.scheduleTraversals被调用
scheduleTraversals();
}
}
void scheduleTraversals() {
if (!mTraversalScheduled) {
mTraversalScheduled = true;
mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
//7. mTraversalRunnable被调用
mChoreographer.postCallback(
Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
if (!mUnbufferedInputDispatch) {
scheduleConsumeBatchedInput();
}
notifyRendererOfFramePending();
pokeDrawLockIfNeeded();
}
}
mTraversalRunnable:
final class TraversalRunnable implements Runnable {
@Override
public void run() {
//7. mTraversalRunnable被调用
doTraversal();
}
void doTraversal() {
if (mTraversalScheduled) {
mTraversalScheduled = false;
mHandler.getLooper().getQueue().removeSyncBarrier(mTraversalBarrier);
if (mProfile) {
Debug.startMethodTracing("ViewAncestor");
}
//8. mTraversalRunnable被调用
performTraversals();
if (mProfile) {
Debug.stopMethodTracing();
mProfile = false;
}
}
}
private void performTraversals() {
......
try {
if (DEBUG_LAYOUT) {
Log.i(mTag, "host=w:" + host.getMeasuredWidth() + ", h:" +
host.getMeasuredHeight() + ", params=" + params);
}
if (mAttachInfo.mThreadedRenderer != null) {
// relayoutWindow may decide to destroy mSurface. As that decision
// happens in WindowManager service, we need to be defensive here
// and stop using the surface in case it gets destroyed.
if (mAttachInfo.mThreadedRenderer.pause()) {
// Animations were running so we need to push a frame
// to resume them
mDirty.set(0, 0, mWidth, mHeight);
}
mChoreographer.mFrameInfo.addFlags(FrameInfo.FLAG_WINDOW_LAYOUT_CHANGED);
}
//8. 最终调用到了relayoutWindow
relayoutResult = relayoutWindow(params, viewVisibility, insetsPending);
}
......
}
private int relayoutWindow(WindowManager.LayoutParams params, int viewVisibility,
boolean insetsPending) throws RemoteException {
......
int relayoutResult = mWindowSession.relayout(mWindow, mSeq, params,
(int) (mView.getMeasuredWidth() * appScale + 0.5f),
(int) (mView.getMeasuredHeight() * appScale + 0.5f), viewVisibility,
insetsPending ? WindowManagerGlobal.RELAYOUT_INSETS_PENDING : 0, frameNumber,
mTmpFrame, mPendingOverscanInsets, mPendingContentInsets, mPendingVisibleInsets,
mPendingStableInsets, mPendingOutsets, mPendingBackDropFrame, mPendingDisplayCutout,
mPendingMergedConfiguration, mSurfaceControl, mTempInsets);
if (mSurfaceControl.isValid()) {
//9.到这里mSurface被真正赋值
mSurface.copyFrom(mSurfaceControl);
} else {
destroySurface();
}
......
}
2.1.6 Choreographer的创建:ViewRootImpl拥有Choreographer
回到2.1.5中的方法addView,在addView中,在调用root.setView之前,必须先创建ViewRootImpl对象,在ViewRootImpl构造函数中它的成员变量mChoreographer
保存了Choreographer的实例,这样Choreographer得到了初始化,包括对应的Handler的初始化,FrameDisplayEventReceiver初始化以及一帧所需要时间的初始化等。 当UI发生改变的时候,Choreographer作为一个节拍器在让界面按照一定节奏进行绘制。这后面可以单独拿一篇分享进行讲解Choreographer的工作原理。
/frameworks/base/core/java/android/view/WindowManagerGlobal.java
public void addView(View view, ViewGroup.LayoutParams params,
Display display, Window parentWindow) {
......
root = new ViewRootImpl(view.getContext(), display);
view.setLayoutParams(wparams);
mViews.add(view);
mRoots.add(root);
mParams.add(wparams);
// do this last because it fires off messages to start doing things
try {
root.setView(view, wparams, panelParentView);
} catch (RuntimeException e) {
// BadTokenException or InvalidDisplayException, clean up.
if (index >= 0) {
removeViewLocked(index, true);
}
throw e;
}
}
......
} frameworks/base/core/java/android/view/ViewRootImpl.java
public ViewRootImpl(Context context, Display display) {
......
mNoncompatDensity = context.getResources().getDisplayMetrics().noncompatDensityDpi;
mFallbackEventHandler = new PhoneFallbackEventHandler(context);
mChoreographer = Choreographer.getInstance();
mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
......
}frameworks/base/core/java/android/view/Choreographer.java
private Choreographer(Looper looper, int vsyncSource) {
mLooper = looper;
mHandler = new FrameHandler(looper);
mDisplayEventReceiver = USE_VSYNC
? new FrameDisplayEventReceiver(looper, vsyncSource)
: null;
mLastFrameTimeNanos = Long.MIN_VALUE;
mFrameIntervalNanos = (long)(1000000000 / getRefreshRate());
mCallbackQueues = new CallbackQueue[CALLBACK_LAST + 1];
for (int i = 0; i <= CALLBACK_LAST; i++) {
mCallbackQueues[i] = new CallbackQueue();
}
// b/68769804: For low FPS experiments.
setFPSDivisor(SystemProperties.getInt(ThreadedRenderer.DEBUG_FPS_DIVISOR, 1));
}2.1.7 Activity、PhoneWindow(Window)、DecorView、ViewRootImpl和Surface之间的关系说明什么

问:
Activity、PhoneWindow(Window)、DecorView、ViewRootImpl和Surface之间的关系说明什么?
答:
- 应用通过Activity、PhoneWindow(Window)、DecorView、ViewRootImpl和Surface之间的关系,最终持有了Surface.可以在这个Surface进行界面的绘制
- 我们做性能的或者框架的,在和App谈显示界面的时候我们需要谈的是:Activity,Window,在和SurfaceFlinger谈界面的时候,我们需要谈的是:Surface,Layer。这样 沟通起来比较没有障碍。这就类似于,"和书生得谈书,和屠夫得谈猪",找到业务交集或者是共同话题。
- 一个Window会对应一个surface,一个surface对应一个Layer, 既然只有一块surface,那么意味着Window中所有界面元素共享一块surface, 在系统中WMS作为界面管理的主要服务,它会知晓所有Window的状态,并且对其进行控制,也就说对于大多数app而言,wms是他和SurfaceFlinger进行沟通的桥梁,
问:
存不存在没有这个桥梁的呢?
答:
有,那就SurfaceView,它和WMS的联系就没这么紧密
2.2 SurfaceView
这里也只是简单的介绍一下他的概念,后面可以用一篇分享来详细介绍
SurfaceView拥有独立的surface。你可以控制这个Surface的格式,比如:大小;SurfaceView负责将Surface放置在屏幕上的正确位置 ,SurfaceView里面镶嵌的Surface是在包含SurfaceView的宿主窗口,即:顶层视图对应的Surface后面;SurfaceView在其窗口中打一个孔这样它的Surface可以得到显示。这里说的“打孔”实际上只不过是在其宿主窗口上设置了一块透明区域,这样它的UI可以漏出来。SurfaceView的绘制方式比普通窗口高,因为SurfaceView的窗口刷新的时候不需要重绘应用程序的窗口,普通窗口的视图绘制机制是逐层刷新的,任何一个子元素刷新都会导致整个视图结构全部重绘一次。

2.3 Layer的创建
Layer的创建我们要回到2.1.5,在2.1.5中流程图中,回去调用relayoutWindow去创建surface,我们来看一下relayoutWindow除了创建surface还干了什么
由上图可知,relayoutWindow去创建surface,还会触发SurfaceFlinge去创建一个Layer
frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
public int relayoutWindow(Session session, IWindow client, int seq, LayoutParams attrs,
int requestedWidth, int requestedHeight, int viewVisibility, int flags,
long frameNumber, Rect outFrame, Rect outOverscanInsets, Rect outContentInsets,
Rect outVisibleInsets, Rect outStableInsets, Rect outOutsets, Rect outBackdropFrame,
DisplayCutout.ParcelableWrapper outCutout, MergedConfiguration mergedConfiguration,
SurfaceControl outSurfaceControl, InsetsState outInsetsState){
......
if (shouldRelayout) {
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "relayoutWindow: viewVisibility_1");
result = win.relayoutVisibleWindow(result, attrChanges);
try {
//创建SurfaceContorl
result = createSurfaceControl(outSurfaceControl, result, win, winAnimator);
} catch (Exception e) {
displayContent.getInputMonitor().updateInputWindowsLw(true /*force*/);
Slog.w(TAG_WM, "Exception thrown when creating surface for client "
+ client + " (" + win.mAttrs.getTitle() + ")",
e);
Binder.restoreCallingIdentity(origId);
return 0;
}
if ((result & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0) {
focusMayChange = true;
}
if (win.mAttrs.type == TYPE_INPUT_METHOD
&& displayContent.mInputMethodWindow == null) {
displayContent.setInputMethodWindowLocked(win);
imMayMove = true;
}
win.adjustStartingWindowFlags();
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
......
}
private int createSurfaceControl(SurfaceControl outSurfaceControl, int result, WindowState win,
WindowStateAnimator winAnimator) {
if (!win.mHasSurface) {
result |= RELAYOUT_RES_SURFACE_CHANGED;
}
WindowSurfaceController surfaceController;
try {
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "createSurfaceControl");
// 2.在createSurfaceControl调用winAnimator.createSurfaceLocked创建
surfaceController = winAnimator.createSurfaceLocked(win.mAttrs.type, win.mOwnerUid);
} finally {
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
if (surfaceController != null) {
surfaceController.getSurfaceControl(outSurfaceControl);
if (SHOW_TRANSACTIONS) Slog.i(TAG_WM, " OUT SURFACE " + outSurfaceControl + ": copied");
} else {
// For some reason there isn't a surface. Clear the
// caller's object so they see the same state.
Slog.w(TAG_WM, "Failed to create surface control for " + win);
outSurfaceControl.release();
}
return result;
}
/frameworks/base/services/core/java/com/android/server/wm/WindowStateAnimator.java
WindowSurfaceController createSurfaceLocked(int windowType, int ownerUid) {
final WindowState w = mWin;
if (mSurfaceController != null) {
return mSurfaceController;
}
mChildrenDetached = false;
if ((mWin.mAttrs.privateFlags & PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY) != 0) {
windowType = SurfaceControl.WINDOW_TYPE_DONT_SCREENSHOT;
}
w.setHasSurface(false);
if (DEBUG_ANIM || DEBUG_ORIENTATION) Slog.i(TAG,
"createSurface " + this + ": mDrawState=DRAW_PENDING");
resetDrawState();
mService.makeWindowFreezingScreenIfNeededLocked(w);
int flags = SurfaceControl.HIDDEN;
final WindowManager.LayoutParams attrs = w.mAttrs;
if (mService.isSecureLocked(w)) {
flags |= SurfaceControl.SECURE;
}
calculateSurfaceBounds(w, attrs, mTmpSize);
final int width = mTmpSize.width();
final int height = mTmpSize.height();
if (DEBUG_VISIBILITY) {
Slog.v(TAG, "Creating surface in session "
+ mSession.mSurfaceSession + " window " + this
+ " w=" + width + " h=" + height
+ " x=" + mTmpSize.left + " y=" + mTmpSize.top
+ " format=" + attrs.format + " flags=" + flags);
}
// We may abort, so initialize to defaults.
mLastClipRect.set(0, 0, 0, 0);
// Set up surface control with initial size.
try {
final boolean isHwAccelerated = (attrs.flags & FLAG_HARDWARE_ACCELERATED) != 0;
final int format = isHwAccelerated ? PixelFormat.TRANSLUCENT : attrs.format;
if (!PixelFormat.formatHasAlpha(attrs.format)
// Don't make surface with surfaceInsets opaque as they display a
// translucent shadow.
&& attrs.surfaceInsets.left == 0
&& attrs.surfaceInsets.top == 0
&& attrs.surfaceInsets.right == 0
&& attrs.surfaceInsets.bottom == 0
// Don't make surface opaque when resizing to reduce the amount of
// artifacts shown in areas the app isn't drawing content to.
&& !w.isDragResizing()) {
flags |= SurfaceControl.OPAQUE;
}
//创建mSurfaceController
mSurfaceController = new WindowSurfaceController(mSession.mSurfaceSession,
attrs.getTitle().toString(), width, height, format, flags, this,
windowType, ownerUid);
mSurfaceController.setColorSpaceAgnostic((attrs.privateFlags
& WindowManager.LayoutParams.PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC) != 0);
setOffsetPositionForStackResize(false);
mSurfaceFormat = format;
w.setHasSurface(true);
if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) {
Slog.i(TAG, " CREATE SURFACE "
+ mSurfaceController + " IN SESSION "
+ mSession.mSurfaceSession
+ ": pid=" + mSession.mPid + " format="
+ attrs.format + " flags=0x"
+ Integer.toHexString(flags)
+ " / " + this);
}
} catch (OutOfResourcesException e) {
Slog.w(TAG, "OutOfResourcesException creating surface");
mService.mRoot.reclaimSomeSurfaceMemory(this, "create", true);
mDrawState = NO_SURFACE;
return null;
} catch (Exception e) {
Slog.e(TAG, "Exception creating surface (parent dead?)", e);
mDrawState = NO_SURFACE;
return null;
}
if (WindowManagerService.localLOGV) Slog.v(TAG, "Got surface: " + mSurfaceController
+ ", set left=" + w.getFrameLw().left + " top=" + w.getFrameLw().top);
if (SHOW_LIGHT_TRANSACTIONS) {
Slog.i(TAG, ">>> OPEN TRANSACTION createSurfaceLocked");
WindowManagerService.logSurface(w, "CREATE pos=("
+ w.getFrameLw().left + "," + w.getFrameLw().top + ") ("
+ width + "x" + height + ")" + " HIDE", false);
}
mLastHidden = true;
if (WindowManagerService.localLOGV) Slog.v(TAG, "Created surface " + this);
return mSurfaceController;
}frameworks/base/services/core/java/com/android/server/wm/WindowSurfaceController.java
public WindowSurfaceController(SurfaceSession s, String name, int w, int h, int format,
int flags, WindowStateAnimator animator, int windowType, int ownerUid) {
//通过SurfaceControl.Builder构造一个mSurfaceControl
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "new SurfaceControl");
final SurfaceControl.Builder b = win.makeSurface()
.setParent(win.getSurfaceControl())
.setName(name)
.setBufferSize(w, h)
.setFormat(format)
.setFlags(flags)
.setMetadata(METADATA_WINDOW_TYPE, windowType)
.setMetadata(METADATA_OWNER_UID, ownerUid);
mSurfaceControl = b.build();
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}/frameworks/base/core/java/android/view/SurfaceControl.java
public SurfaceControl build() {
if (mWidth < 0 || mHeight < 0) {
throw new IllegalStateException(
"width and height must be positive or unset");
}
if ((mWidth > 0 || mHeight > 0) && (isColorLayerSet() || isContainerLayerSet())) {
throw new IllegalStateException(
"Only buffer layers can set a valid buffer size.");
}
return new SurfaceControl(
mSession, mName, mWidth, mHeight, mFormat, mFlags, mParent, mMetadata);
}
private SurfaceControl(SurfaceSession session, String name, int w, int h, int format, int flags,
SurfaceControl parent, SparseIntArray metadata)
throws OutOfResourcesException, IllegalArgumentException {
......
mName = name;
mWidth = w;
mHeight = h;
Parcel metaParcel = Parcel.obtain();
try {
if (metadata != null && metadata.size() > 0) {
metaParcel.writeInt(metadata.size());
for (int i = 0; i < metadata.size(); ++i) {
metaParcel.writeInt(metadata.keyAt(i));
metaParcel.writeByteArray(
ByteBuffer.allocate(4).order(ByteOrder.nativeOrder())
.putInt(metadata.valueAt(i)).array());
}
metaParcel.setDataPosition(0);
}
//调用nativeCreate创建对象
mNativeObject = nativeCreate(session, name, w, h, format, flags,
parent != null ? parent.mNativeObject : 0, metaParcel);
} finally {
metaParcel.recycle();
}
if (mNativeObject == 0) {
throw new OutOfResourcesException(
"Couldn't allocate SurfaceControl native object");
}
mCloseGuard.open("release");
}frameworks/base/core/jni/android_view_SurfaceControl.cpp
static jlong nativeCreate(JNIEnv* env, jclass clazz, jobject sessionObj,
jstring nameStr, jint w, jint h, jint format, jint flags, jlong parentObject,
jobject metadataParcel) {
ScopedUtfChars name(env, nameStr);
sp<SurfaceComposerClient> client;
if (sessionObj != NULL) {
client = android_view_SurfaceSession_getClient(env, sessionObj);
} else {
client = SurfaceComposerClient::getDefault();
}
SurfaceControl *parent = reinterpret_cast<SurfaceControl*>(parentObject);
sp<SurfaceControl> surface;
LayerMetadata metadata;
Parcel* parcel = parcelForJavaObject(env, metadataParcel);
if (parcel && !parcel->objectsCount()) {
status_t err = metadata.readFromParcel(parcel);
if (err != NO_ERROR) {
jniThrowException(env, "java/lang/IllegalArgumentException",
"Metadata parcel has wrong format");
}
}
status_t err = client->createSurfaceChecked(
String8(name.c_str()), w, h, format, &surface, flags, parent, std::move(metadata));
if (err == NAME_NOT_FOUND) {
jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
return 0;
} else if (err != NO_ERROR) {
jniThrowException(env, OutOfResourcesException, NULL);
return 0;
}
surface->incStrong((void *)nativeCreate);
return reinterpret_cast<jlong>(surface.get());
}frameworks/native/libs/gui/SurfaceComposerClient.cpp
status_t SurfaceComposerClient::createSurfaceChecked(const String8& name, uint32_t w, uint32_t h,
PixelFormat format,
sp<SurfaceControl>* outSurface, uint32_t flags,
SurfaceControl* parent,
LayerMetadata metadata) {
sp<SurfaceControl> sur;
status_t err = mStatus;
if (mStatus == NO_ERROR) {
sp<IBinder> handle;
sp<IBinder> parentHandle;
sp<IGraphicBufferProducer> gbp;
if (parent != nullptr) {
parentHandle = parent->getHandle();
}
err = mClient->createSurface(name, w, h, format, flags, parentHandle, std::move(metadata),
&handle, &gbp);
ALOGE_IF(err, "SurfaceComposerClient::createSurface error %s", strerror(-err));
if (err == NO_ERROR) {
*outSurface = new SurfaceControl(this, handle, gbp, true /* owned */);
}
}
return err;
}/frameworks/native/services/surfaceflinger/Client.cpp
status_t Client::createSurface(const String8& name, uint32_t w, uint32_t h, PixelFormat format,
uint32_t flags, const sp<IBinder>& parentHandle,
LayerMetadata metadata, sp<IBinder>* handle,
sp<IGraphicBufferProducer>* gbp) {
// We rely on createLayer to check permissions.
return mFlinger->createLayer(name, this, w, h, format, flags, std::move(metadata), handle, gbp,
parentHandle);
}3. 总结和后续分享计划
3.1 总结

- handleLaunchActivity 调用performLaunchActivity创建一个Activity,这些都是跑在ActivityThread中的,也就是应用的主线程,到这来就APP就拥有了Activity;
- 调用到performLaunchActivity不仅会会创建Actvity,还会创建Application,同时还会调用,调用 activity.attach,通过该方法创建一个Window,由于Window本身是个抽象类,因此在创建的时候会创建它的具体实现类PhoneWindow,到这里Actvity拥有了自己的Window:mWindow;
- 调用到performLaunchActivity后不仅会创建Actvity和Application和window,还会调用mInstrumentation.callActivityOnCreate,这个最终会调用调应用自己实现的具体Activity类中去,调用的该具体类的Actvity的OnCreate,,应用会在这里调用setContentView.Activity的setContentView被调用,在这个函数中会去调用对应PhoneWindow的setContentView,Window的setContentView,在这个函数中会通过installDecor来为PhoneWindow创建DecorVIew,到这来Window拥有了自己的DecorView:mDecor;
- DecorView中的方法很多都是通过getViewRootImpl去调用ViewRootImpl去实现的,DecorView的成员变量中虽然没有保存ViewRootImpl,但是它还是一直持有ViewRootImpl的引用,这个相当于DecorView拥有了ViewRootImpl;
- 当Activity创建的时候会走到Activity的onCreate这个生命周期函数,同样的当应用到前台的时候,会AMS会通过Binder调用最终调用调handleResumeActivity,最终是在relayoutWindow的时候,ViewRootImpl成员变量mSurface才真正赋值,到这里ViewRootImp,通过copyFrom的方式拥有了自己的Surface
- 一个Window会对应一个surface,同时对应一个Layer, Window中所有界面元素共享一块surface, 在系统中WMS作为界面管理的主要服务,它会知晓所有Window的状态,并且对其进行控制,也就说对于大多数app而言,wms是他和SurfaceFlinger进行沟通的桥梁,但是surfaceview某种程度上可以“绕过”wms。SurfaceView拥有独立的surface。你可以控制这个Surface的格式,比如:大小;SurfaceView负责将Surface放置在屏幕上的正确位置 ,SurfaceView里面镶嵌的Surface是在包含SurfaceView的宿主窗口即:顶层视图对应的Surface后面;SurfaceView在其窗口中打一个孔这样它的Surface可以得到显示。这里说的“打孔”实际上只不过是在其宿主窗口上设置了一块透明区域,这样它的UI可以漏出来。SurfaceView的绘制方式比普通窗口高,因为SurfaceView的窗口刷新的时候不需要重绘应用程序的窗口,普通窗口的视图绘制机制是一层一层的,任何一个子元素刷新都会导致整个视图结构全部重绘一次
3.2 分享计划
下图是显示子系统中经常可以见到的一些关键词,也是构成整个系统的关键因素,后续分享会围绕如下关键字展开,可能是讲单个也有可能几个串起来一起讲。
