Android L Display System源码分析(6):App 界面显示流程源码分析 之 Window加载显示流程分析(Android 9.0 && Kernel 3.18)


注:文章都是通过阅读各位前辈总结的资料 Android 9.0 && Linux(Kernel 3.18)Qualcomm平台源码、加上自己的思考分析总结出来的,其中难免有理解不对的地方,欢迎大家批评指正。文章为个人学习、研究、欣赏之用,图文内容整理自互联网,如有侵权,请联系删除(◕‿◕),转载请注明出处(©Qualcomm ©Android @Linux 版权所有),谢谢。
(==文章基于 Kernel-3.18==)&&(==文章基于 Android 9.0==)
【zhoujinjian.cc博客原图链接】
【开发板 Intrinsyc Open-Q™ 820 µSOM Development Kit】
【开发板 Android 9.0 && Linux(Kernel 3.18)源码链接】

正是由于前人的分析和总结,帮助我节约了大量的时间和精力,特别感谢!!!

(1)【Android Display System】


==源码(部分)==:
packages/apps/testViewportGreen && testViewportBlue && testViewportRed/
frameworks/base/core/java/android/app/
frameworks/base/services/core/java/com/android/server/wm/
frameworks/base/services/core/java/com/android/server/am/
frameworks/base/services/core/java/com/android/server/policy/
frameworks/native/services/surfaceflinger/
frameworks/native/libs/gui/
frameworks/native/libs/ui/


enter image description here

(一)、Window添加过程

(1)、ActivityThread.performLaunchActivity()

接着上一篇文章开始分析,performLaunchActivity()方法完成了两件事:

G:\android9.0\frameworks\base\core\java\android\app\ActivityThread.java

    /**  Core implementation of activity launch. */
    private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        ActivityInfo aInfo = r.activityInfo;
        ......
        ComponentName component = r.intent.getComponent();
        ......

        ContextImpl appContext = createBaseContextForActivity(r);
        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) {
            ......
        }

        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;
                ......
                appContext.setOuterContext(activity);
                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);

                if (customIntent != null) {
                    activity.mIntent = customIntent;
                }
                r.lastNonConfigurationInstances = null;
                checkAndBlockForNetworkAccess();
                activity.mStartedActivity = false;
                int theme = r.activityInfo.getThemeResource();
                if (theme != 0) {
                    activity.setTheme(theme);
                }

                activity.mCalled = false;
                if (r.isPersistable()) {
                    mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
                } else {
                    mInstrumentation.callActivityOnCreate(activity, r.state);
                }
                ......
                r.activity = activity;
            }
            r.setState(ON_CREATE);

            mActivities.put(r.token, r);

        } catch (SuperNotCalledException e) {
            throw e;

        } catch (Exception e) {
            .......
        }

        return activity;
    }
  • Activity窗口对象PhoneWindow的创建,通过attach函数来完成;
G:\android9.0\frameworks\base\core\java\android\app\Activity.java

    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) {
        attachBaseContext(context);

        mFragments.attachHost(null /*parent*/);

        mWindow = new PhoneWindow(this, window, activityConfigCallback);
        mWindow.setWindowControllerCallback(this);
        mWindow.setCallback(this);
        mWindow.setOnWindowDismissedCallback(this);
        mWindow.getLayoutInflater().setPrivateFactory(this);
        if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) {
            mWindow.setSoftInputMode(info.softInputMode);
        }
        if (info.uiOptions != 0) {
            mWindow.setUiOptions(info.uiOptions);
        }
        mUiThread = Thread.currentThread();

        mMainThread = aThread;
        mInstrumentation = instr;
        mToken = token;
        mIdent = ident;
        mApplication = application;
        mIntent = intent;
        mReferrer = referrer;
        mComponent = intent.getComponent();
        mActivityInfo = info;
        mTitle = title;
        mParent = parent;
        mEmbeddedID = id;
        mLastNonConfigurationInstances = lastNonConfigurationInstances;
        if (voiceInteractor != null) {
            if (lastNonConfigurationInstances != null) {
                mVoiceInteractor = lastNonConfigurationInstances.voiceInteractor;
            } else {
                mVoiceInteractor = new VoiceInteractor(voiceInteractor, this, this,
                        Looper.myLooper());
            }
        }

        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();
        mCurrentConfig = config;

        mWindow.setColorMode(info.colorMode);

        setAutofillCompatibilityEnabled(application.isAutofillCompatibilityEnabled());
        enableAutofillCompatibilityIfNeeded();
    }
  • Activity视图对象的创建,通过callActivityOnCreate >>> setContentView函数来完成;
(2)、Activity.setContentView()
G:\android9.0\frameworks\base\core\java\android\app\Activity.java

final void performCreate(Bundle icicle, PersistableBundle persistentState) {
    mCanEnterPictureInPicture = true;
    restoreHasCurrentPermissionRequest(icicle);
    if (persistentState != null) {
        onCreate(icicle, persistentState);
    } else {
        onCreate(icicle);
    }
    writeEventLog(LOG_AM_ON_CREATE_CALLED, "performCreate");
    mActivityTransitionState.readState(icicle);

    mVisibleFromClient = !mWindow.getWindowStyle().getBoolean(
            com.android.internal.R.styleable.Window_windowNoDisplay, false);
    mFragments.dispatchActivityCreated();
    mActivityTransitionState.setEnterActivityOptions(this, getActivityOptions());
}
G:\android9.0\frameworks\base\core\java\android\app\Activity.java

    public void setContentView(@LayoutRes int layoutResID) {
        getWindow().setContentView(layoutResID);
        initWindowDecorActionBar();
    }

getWindow()函数得到前面创建的窗口对象PhoneWindow,通过PhoneWindow来设置Activity的视图。
[->PhoneWindow.java]

G:\android9.0\frameworks\base\core\java\com\android\internal\policy\PhoneWindow.java
    @Override
    public void setContentView(int layoutResID) {
        if (mContentParent == null) {
            installDecor();
        } else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
            mContentParent.removeAllViews();
        }

        if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
            final Scene newScene = Scene.getSceneForLayout(mContentParent, layoutResID,
                    getContext());
            transitionTo(newScene);
        } else {
            mLayoutInflater.inflate(layoutResID, mContentParent);
        }
        mContentParent.requestApplyInsets();
        final Callback cb = getCallback();
        if (cb != null && !isDestroyed()) {
            cb.onContentChanged();
        }
        mContentParentExplicitlySet = true;
    }

Activity.onCreate()会调用setContentView(),整个过程主要是Activity的布局文件或View添加至窗口里,
详细过程不再赘述,详细加载过程请参考: Android应用setContentView与LayoutInflater加载解析机制源码分析
重点概括为:

● 创建一个DecorView的对象mDecor,该mDecor对象将作为整个应用窗口的根视图。
● 依据Feature等style theme创建不同的窗口修饰布局文件,并且通过findViewById获取Activity布局文件该存放的地方(窗口修饰布局文件中id为content的FrameLayout)。
● 将Activity的布局文件添加至id为content的FrameLayout内。
● 当setContentView设置显示OK以后会回调Activity的onContentChanged方法。Activity的各种View的findViewById()方法等都可以放到该方法中,系统会帮忙回调。
(3)、ActivityThread.handleResumeActivity()

在调用完performLaunchActivity()方法之后,其有掉用了handleResumeActivity()法。

G:\android9.0\frameworks\base\core\java\android\app\ActivityThread.java

    @Override
    public void handleResumeActivity(IBinder token, boolean finalStateRequest, boolean isForward,
            String reason) {
        unscheduleGcIdler();
        mSomeActivitiesChanged = true;

        // TODO Push resumeArgs into the activity for consideration
        final ActivityClientRecord r = performResumeActivity(token, finalStateRequest, reason);
        ......
        final Activity a = r.activity;

        if (localLOGV) {
            Slog.v(TAG, "Resume " + r + " started activity: " + a.mStartedActivity
                    + ", hideForNow: " + r.hideForNow + ", finished: " + a.mFinished);
        }

        final int forwardBit = isForward
                ? WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION : 0;

        ......
        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;
            l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
            l.softInputMode |= forwardBit;
            ......
            if (a.mVisibleFromClient) {
                if (!a.mWindowAdded) {
                    a.mWindowAdded = true;
                    wm.addView(decor, l);
                } else {
                    a.onWindowAttributesChanged(l);
                }
            }
        } else if (!willBeVisible) {
            r.hideForNow = true;
        }

        cleanUpPendingRemoveWindows(r, false /* force */);

        if (!r.activity.mFinished && willBeVisible && r.activity.mDecor != null && !r.hideForNow) {
            if (r.newConfig != null) {
                performConfigurationChangedForActivity(r, r.newConfig);
                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) {
                r.activity.makeVisible();
            }
        }

        r.nextIdle = mNewActivities;
        mNewActivities = r;
        if (localLOGV) Slog.v(TAG, "Scheduling idle handler for " + r);
        Looper.myQueue().addIdleHandler(new Idler());
    }

我们知道,在前面的performLaunchActivity函数中完成Activity的创建后,会将当前当前创建的Activity在应用程序进程端的描述符ActivityClientRecord以键值对的形式保存到ActivityThread的成员变量mActivities中:mActivities.put(r.token, r);,r.token就是Activity的身份证,即是IApplicationToken.Proxy代理对象,也用于与AMS通信。上面的函数首先通过performResumeActivity从mActivities变量中取出Activity的应用程序端描述符ActivityClientRecord,然后取出前面为Activity创建的视图对象DecorView和窗口管理器WindowManager,最后将视图对象添加到窗口管理器中。

(4)、ViewManager.addView()

ViewManager.addView()真正实现的的地方在WindowManagerImpl.java中

G:\android9.0\frameworks\base\core\java\android\view\ViewManager.java

public interface ViewManager
{
public void addView(View view, ViewGroup.LayoutParams params);
public void updateViewLayout(View view, ViewGroup.LayoutParams params);
public void removeView(View view);
}

[->WindowManagerImpl.java]

G:\android9.0\frameworks\base\core\java\android\view\WindowManagerImpl.java

Override
public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
    ......
    mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow);
}

[->WindowManagerGlobal.java]

G:\android9.0\frameworks\base\core\java\android\view\WindowManagerGlobal.java

    public void addView(View view, ViewGroup.LayoutParams params,
        Display display, Window parentWindow) {
    final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams) params;
    if (parentWindow != null) {
        parentWindow.adjustLayoutParamsForSubWindow(wparams);
    } else {
        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) {
        ......
        root = new ViewRootImpl(view.getContext(), display);
        view.setLayoutParams(wparams);
        mViews.add(view);
        mRoots.add(root);
        mParams.add(wparams);
    }
    try {
        root.setView(view, wparams, panelParentView);
    } 
    ......
}
(5)、ViewRootImpl.setView()
5.1、ViewRootImpl()构造过程
G:\android9.0\frameworks\base\core\java\android\view\ViewRootImpl.java

    final W mWindow;
    final Surface mSurface = new Surface();
    final ViewRootHandler mHandler = new ViewRootHandler();
    ......

    public ViewRootImpl(Context context, Display display) {
        mContext = context;
        mWindowSession = WindowManagerGlobal.getWindowSession();
        mDisplay = display;
        mBasePackageName = context.getBasePackageName();
        mThread = Thread.currentThread();
        mLocation = new WindowLeaked(null);
        mLocation.fillInStackTrace();
        mWidth = -1;
        mHeight = -1;
        mDirty = new Rect();
        mTempRect = new Rect();
        mVisRect = new Rect();
        mWinFrame = new Rect();
        mWindow = new W(this);
        mTargetSdkVersion = context.getApplicationInfo().targetSdkVersion;
        mViewVisibility = View.GONE;
        mTransparentRegion = new Region();
        mPreviousTransparentRegion = new Region();
        mFirst = true; // true for the first time the view is added
        mAdded = false;
        mAttachInfo = new View.AttachInfo(mWindowSession, mWindow, display, this, mHandler, this,
                context);
        mAccessibilityManager = AccessibilityManager.getInstance(context);
        mAccessibilityManager.addAccessibilityStateChangeListener(
                mAccessibilityInteractionConnectionManager, mHandler);
        mHighContrastTextManager = new HighContrastTextManager();
        mAccessibilityManager.addHighTextContrastStateChangeListener(
                mHighContrastTextManager, mHandler);
        mViewConfiguration = ViewConfiguration.get(context);
        mDensity = context.getResources().getDisplayMetrics().densityDpi;
        mNoncompatDensity = context.getResources().getDisplayMetrics().noncompatDensityDpi;
        mFallbackEventHandler = new PhoneFallbackEventHandler(context);
        mChoreographer = Choreographer.getInstance();
        mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
        loadSystemProperties();
        mPerf = new BoostFramework(context);
    }

在ViewRootImpl的构造函数中初始化了一些成员变量,ViewRootImpl创建了以下几个主要对象:

(1) 通过WindowManagerGlobal.getWindowSession()得到IWindowSession的代理对象,该对象用于和WMS通信。

(2) 创建了一个W本地Binder对象,用于WMS与APP进程通信。

(3) 采用单例模式创建了一个Choreographer对象,用于统一调度窗口绘图。

(4) 创建ViewRootHandler对象,用于处理当前视图消息。

(5) 构造一个AttachInfo对象;

(6) 创建Surface对象,用于绘制当前视图,当然该Surface对象的真正创建是由WMS来完成的,只不过是WMS传递给应用程序进程的。

5.1.1、IWindowSession代理获取过程
G:\android9.0\frameworks\base\core\java\android\view\WindowManagerGlobal.java

    public static IWindowSession getWindowSession() {
        synchronized (WindowManagerGlobal.class) {
            if (sWindowSession == null) {
                try {
                    InputMethodManager imm = InputMethodManager.getInstance();
                    IWindowManager windowManager = getWindowManagerService();
                    sWindowSession = windowManager.openSession(
                            new IWindowSessionCallback.Stub() {
                                @Override
                                public void onAnimatorScaleChanged(float scale) {
                                    ValueAnimator.setDurationScale(scale);
                                }
                            },
                            imm.getClient(), imm.getInputContext());
                } catch (RemoteException e) {
                    throw e.rethrowFromSystemServer();
                }
            }
            return sWindowSession;
        }
    }
5.1.1.1、WindowManagerService.openSession()

通过Binder通信WindowManagerService.openSession()
通过WMS的openSession函数创建应用程序与WMS之间的连接通道,即获取IWindowSession代理对象,并将该代理对象保存到ViewRootImpl的静态成员变量sWindowSession中,因此在应用程序进程中有且只有一个IWindowSession代理对象。

G:\android9.0\frameworks\base\services\core\java\com\android\server\wm\WindowManagerService.java

    @Override
    public IWindowSession openSession(IWindowSessionCallback callback, IInputMethodClient client,
            IInputContext inputContext) {
        if (client == null) throw new IllegalArgumentException("null client");
        if (inputContext == null) throw new IllegalArgumentException("null inputContext");
        Session session = new Session(this, callback, client, inputContext);
        return session;
    }
5.1.1.2、new Session()

在WMS服务端构造了一个Session实例对象。ViewRootImpl 是一很重要的类,类似 ActivityThread 负责跟AmS通信一样,ViewRootImpl 的一个重要职责就是跟 WmS 通信,它通静态变量 sWindowSession(IWindowSession实例)与 WmS 进行通信。每个应用进程,仅有一个 sWindowSession 对象,它对应了 WmS 中的 Session 子类,WmS 为每一个应用进程分配一个 Session 对象。WindowState 类有一个 IWindow mClient 参数,是在构造方法中赋值的,是由 Session 调用 addWindow 传递过来了,对应了 ViewRootImpl 中的 W 类的实例。

G:\android9.0\frameworks\base\services\core\java\com\android\server\wm\Session.java

class Session extends IWindowSession.Stub implements IBinder.DeathRecipient {
    final WindowManagerService mService;
    final IWindowSessionCallback mCallback;
    final IInputMethodClient mClient;
    final int mUid;
    final int mPid;
    private final String mStringName;
    SurfaceSession mSurfaceSession;
    private int mNumWindow = 0;
    // Set of visible application overlay window surfaces connected to this session.
    private final Set<WindowSurfaceController> mAppOverlaySurfaces = new HashSet<>();
    // Set of visible alert window surfaces connected to this session.
    private final Set<WindowSurfaceController> mAlertWindowSurfaces = new HashSet<>();
    private final DragDropController mDragDropController;
    final boolean mCanAddInternalSystemWindow;
    final boolean mCanHideNonSystemOverlayWindows;
    final boolean mCanAcquireSleepToken;
    private AlertWindowNotification mAlertWindowNotification;
    private boolean mShowingAlertWindowNotificationAllowed;
    private boolean mClientDead = false;
    private float mLastReportedAnimatorScale;
    private String mPackageName;
    private String mRelayoutTag;

    public Session(WindowManagerService service, IWindowSessionCallback callback,
            IInputMethodClient client, IInputContext inputContext) {
        mService = service;
        mCallback = callback;
        mClient = client;
        ......
        mDragDropController = mService.mDragDropController;
        ......
        synchronized (mService.mWindowMap) {
            if (mService.mInputMethodManager == null && mService.mHaveInputMethods) {
                IBinder b = ServiceManager.getService(
                        Context.INPUT_METHOD_SERVICE);
                mService.mInputMethodManager = IInputMethodManager.Stub.asInterface(b);
            }
        }
        long ident = Binder.clearCallingIdentity();
        try {
            if (mService.mInputMethodManager != null) {
                mService.mInputMethodManager.addClient(client, inputContext,
                        mUid, mPid);
            } else {
                client.setUsingInputMethod(false);
            }
            client.asBinder().linkToDeath(this, 0);
        } catch (RemoteException e) {
           ......
        } finally {
            Binder.restoreCallingIdentity(ident);
        }
    }
5.1.2、创建W本地Binder对象
G:\android9.0\frameworks\base\core\java\android\view\ViewRootImpl.java

static class W extends IWindow.Stub {
    private final WeakReference<ViewRootImpl> mViewAncestor;
    private final IWindowSession mWindowSession;

    W(ViewRootImpl viewAncestor) {
        mViewAncestor = new WeakReference<ViewRootImpl>(viewAncestor);
        mWindowSession = viewAncestor.mWindowSession;
    }
    ......
    }

enter image description here

5.1.3、Choreographer创建
G:\android9.0\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));
    }

G:\android9.0\frameworks\base\core\java\android\view\Choreographer.java
  private final class FrameDisplayEventReceiver extends DisplayEventReceiver
            implements Runnable {
        ......
        public FrameDisplayEventReceiver(Looper looper, int vsyncSource) {
            super(looper, vsyncSource);
        }
        ......
    }

FrameDisplayEventReceiver 继承 DisplayEventReceiver

G:\android9.0\frameworks\base\core\java\android\view\DisplayEventReceiver.java
    public DisplayEventReceiver(Looper looper, int vsyncSource) {
        ......
        mMessageQueue = looper.getQueue();
        mReceiverPtr = nativeInit(new WeakReference<DisplayEventReceiver>(this), mMessageQueue,
                vsyncSource);

        mCloseGuard.open("dispose");
    }
>>>>>>JNI
G:\android9.0\frameworks\base\core\jni\android_view_DisplayEventReceiver.cpp

static jlong nativeInit(JNIEnv* env, jclass clazz, jobject receiverWeak,
        jobject messageQueueObj, jint vsyncSource) {
    sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
    if (messageQueue == NULL) {
        jniThrowRuntimeException(env, "MessageQueue is not initialized.");
        return 0;
    }

    sp<NativeDisplayEventReceiver> receiver = new NativeDisplayEventReceiver(env,
            receiverWeak, messageQueue, vsyncSource);
    status_t status = receiver->initialize();
    if (status) {
        String8 message;
        message.appendFormat("Failed to initialize display event receiver.  status=%d", status);
        jniThrowRuntimeException(env, message.string());
        return 0;
    }

    receiver->incStrong(gDisplayEventReceiverClassInfo.clazz); // retain a reference for the object
    return reinterpret_cast<jlong>(receiver.get());
}


NativeDisplayEventReceiver::NativeDisplayEventReceiver(JNIEnv* env,
        jobject receiverWeak, const sp<MessageQueue>& messageQueue, jint vsyncSource) :
        DisplayEventDispatcher(messageQueue->getLooper(),
                static_cast<ISurfaceComposer::VsyncSource>(vsyncSource)),
        mReceiverWeakGlobal(env->NewGlobalRef(receiverWeak)),
        mMessageQueue(messageQueue) {
    ALOGV("receiver %p ~ Initializing display event receiver.", this);
}

NativeDisplayEventReceiver 继承与DisplayEventDispatcher,所以DisplayEventDispatcher会执行初始化操作。

G:\android9.0\frameworks\base\libs\androidfw\DisplayEventDispatcher.cpp

DisplayEventDispatcher::DisplayEventDispatcher(const sp<Looper>& looper,
        ISurfaceComposer::VsyncSource vsyncSource) :
        mLooper(looper), mReceiver(vsyncSource), mWaitingForVsync(false) {
    ALOGV("dispatcher %p ~ Initializing display event dispatcher.", this);
}

status_t DisplayEventDispatcher::initialize() {
    status_t result = mReceiver.initCheck();
    if (result) {
        ALOGW("Failed to initialize display event receiver, status=%d", result);
        return result;
    }

    int rc = mLooper->addFd(mReceiver.getFd(), 0, Looper::EVENT_INPUT,
            this, NULL);
    if (rc < 0) {
        return UNKNOWN_ERROR;
    }
    return OK;
}

监听mReceiver的所获取的文件句柄,一旦有数据到来,则回调this(此处NativeDisplayEventReceiver)中所复写LooperCallback对象的 handleEvent。

5.1.3.1、Native DisplayEventReceiver初始化

mReceiver为DisplayEventReceiver实例

G:\android9.0\frameworks\native\libs\gui\DisplayEventReceiver.cpp

DisplayEventReceiver::DisplayEventReceiver(ISurfaceComposer::VsyncSource vsyncSource) {
    sp<ISurfaceComposer> sf(ComposerService::getComposerService());
    if (sf != NULL) {
        mEventConnection = sf->createDisplayEventConnection(vsyncSource);
        if (mEventConnection != NULL) {
            mDataChannel = std::make_unique<gui::BitTube>();
            mEventConnection->stealReceiveChannel(mDataChannel.get());
        }
    }
}

此处通过binder通信与SurfaceFlinger建立连接,直接看SurfaceFlinger服务端的实现

5.1.3.2、createDisplayEventConnection
G:\android9.0\frameworks\native\services\surfaceflinger\SurfaceFlinger.cpp
// ----------------------------------------------------------------------------

sp<IDisplayEventConnection> SurfaceFlinger::createDisplayEventConnection(
        ISurfaceComposer::VsyncSource vsyncSource) {
    if (vsyncSource == eVsyncSourceSurfaceFlinger) {
        return mSFEventThread->createEventConnection();
    } else {
        return mEventThread->createEventConnection();
    }
}

我们这里不是eVsyncSourceSurfaceFlinger,所以会走mEventThread->createEventConnection() 分支,为app进程创建一个Connection,会首先调用Connection::onFirstRef(),然后加入到mDisplayEventConnections中。

G:\android9.0\frameworks\native\services\surfaceflinger\EventThread.cpp

sp<BnDisplayEventConnection> EventThread::createEventConnection() const {
    return new Connection(const_cast<EventThread*>(this));
}

EventThread::Connection::Connection(EventThread* eventThread)
      : count(-1), mEventThread(eventThread), mChannel(gui::BitTube::DefaultSize) {}

void EventThread::Connection::onFirstRef() {
    // NOTE: mEventThread doesn't hold a strong reference on us
    mEventThread->registerDisplayEventConnection(this);
}

status_t EventThread::registerDisplayEventConnection(
        const sp<EventThread::Connection>& connection) {
    std::lock_guard<std::mutex> lock(mMutex);
    mDisplayEventConnections.add(connection);
    mCondition.notify_all();
    return NO_ERROR;
}
5.1.3.3、mEventConnection->stealReceiveChannel(mDataChannel.get())

Binder通信直接看服务端实现,将从客户端传来的BitTube设置到接收VSync信号的FD

G:\android9.0\frameworks\native\services\surfaceflinger\EventThread.cpp

status_t EventThread::Connection::stealReceiveChannel(gui::BitTube* outChannel) {
    outChannel->setReceiveFd(mChannel.moveReceiveFd());
    return NO_ERROR;
}

G:\android9.0\frameworks\native\libs\gui\BitTube.cpp
void BitTube::setReceiveFd(base::unique_fd&& receiveFd) {
    mReceiveFd = std::move(receiveFd);
}
5.1.4、构造AttachInfo对象
G:\android9.0\frameworks\base\core\java\android\view\View.java

    final static class AttachInfo {
        ......
        final IWindowSession mSession;
        final IWindow mWindow;
        final IBinder mWindowToken;
        Display mDisplay;
        final Callbacks mRootCallbacks;
        IWindowId mIWindowId;
        WindowId mWindowId;
        View mRootView;
        ......
        final ViewTreeObserver mTreeObserver;
        Canvas mCanvas;
        final ViewRootImpl mViewRootImpl;
        final Handler mHandler;
        ......
        AttachInfo(IWindowSession session, IWindow window, Display display,
                ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer,
                Context context) {
            mSession = session;
            mWindow = window;
            mWindowToken = window.asBinder();
            mDisplay = display;
            mViewRootImpl = viewRootImpl;
            mHandler = handler;
            mRootCallbacks = effectPlayer;
            mTreeObserver = new ViewTreeObserver(context);
        }
5.2、视图View添加过程

窗口管理器WindowManagerImpl为当前添加的窗口创建好各种对象后,调用ViewRootImpl的setView函数向WMS服务添加一个窗口对象。

G:\android9.0\frameworks\base\core\java\android\view\ViewRootImpl.java

    public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
        synchronized (this) {
            if (mView == null) {
                mView = view;//将DecorView保存到ViewRootImpl的成员变量mView中

                mAttachInfo.mDisplayState = mDisplay.getState();
                mDisplayManager.registerDisplayListener(mDisplayListener, mHandler);

                mViewLayoutDirectionInitial = mView.getRawLayoutDirection();
                mFallbackEventHandler.setView(view);
                mWindowAttributes.copyFrom(attrs);
                ......
                attrs = mWindowAttributes;
                setTag();

                ......
                mClientWindowLayoutFlags = attrs.flags;

                setAccessibilityFocus(null, null);

                ......

                CompatibilityInfo compatibilityInfo =
                        mDisplay.getDisplayAdjustments().getCompatibilityInfo();
                mTranslator = compatibilityInfo.getTranslator();

                ......
                if (DEBUG_LAYOUT) Log.d(mTag, "WindowLayout in setView:" + attrs);
---------------------------------------------------
对应Log:
    Line 2310: 04-16 13:08:36.961 D/ViewRootImpl[TestActivity]( 2602): WindowLayout in setView:{(0,0)(fillxfill) sim={forwardNavigation} ty=BASE_APPLICATION fmt=TRANSPARENT wanim=0x1030000
    Line 2311: 04-16 13:08:36.961 D/ViewRootImpl[TestActivity]( 2602):   fl=LAYOUT_IN_SCREEN LAYOUT_INSET_DECOR SPLIT_TOUCH HARDWARE_ACCELERATED}
---------------------------------------------------
                if (!compatibilityInfo.supportsScreen()) {
                    attrs.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
                    mLastInCompatMode = true;
                }

                mSoftInputMode = attrs.softInputMode;
                mWindowAttributesChanged = true;
                mWindowAttributesChangesFlag = WindowManager.LayoutParams.EVERYTHING_CHANGED;
                //同时将DecorView保存到mAttachInfo中  
                mAttachInfo.mRootView = view;
                mAttachInfo.mScalingRequired = mTranslator != null;
                mAttachInfo.mApplicationScale =
                        mTranslator == null ? 1.0f : mTranslator.applicationScale;
                if (panelParentView != null) {
                    mAttachInfo.mPanelParentWindowToken
                            = panelParentView.getApplicationWindowToken();
                }
                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.
                1)在添加窗口前进行UI布局 
                requestLayout();
                if ((mWindowAttributes.inputFeatures
                        & WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) {
                    mInputChannel = new InputChannel();
                }
                mForceDecorViewVisibility = (mWindowAttributes.privateFlags
                        & PRIVATE_FLAG_FORCE_DECOR_VIEW_VISIBILITY) != 0;
                try {
                    mOrigWindowType = mWindowAttributes.type;
                    mAttachInfo.mRecomputeGlobalAttributes = true;
                    collectViewAttributes();

                    // 2)将窗口添加到WMS服务中,mWindow为W本地Binder对象,通过Binder传输到WMS服务端后,变为IWindow代理对象  
                    res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
                            getHostVisibility(), mDisplay.getDisplayId(), mWinFrame,
                            mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
                            mAttachInfo.mOutsets, mAttachInfo.mDisplayCutout, mInputChannel);
                } catch (RemoteException e) {
                    mAdded = false;
                    mView = null;
                    mAttachInfo.mRootView = null;
                    mInputChannel = null;
                    mFallbackEventHandler.setView(null);
                    unscheduleTraversals();
                    setAccessibilityFocus(null, null);
                    throw new RuntimeException("Adding window failed", e);
                } finally {
                    if (restore) {
                        attrs.restore();
                    }
                }

                ......

----------------------------------------------------------------
对应Log:
04-16 13:08:36.968 V/ViewRootImpl[TestActivity]( 2602): Added window android.view.ViewRootImpl$W@ad597e9
----------------------------------------------------------------
                if (DEBUG_LAYOUT) Log.v(mTag, "Added window " + mWindow);
                ......
                //3)建立窗口消息通道  
                if (mInputChannel != null) {
                    if (mInputQueueCallback != null) {
                        mInputQueue = new InputQueue();
                        mInputQueueCallback.onInputQueueCreated(mInputQueue);
                    }
                    mInputEventReceiver = new WindowInputEventReceiver(mInputChannel,
                            Looper.myLooper());
                }

                view.assignParent(this);
                mAddedTouchMode = (res & WindowManagerGlobal.ADD_FLAG_IN_TOUCH_MODE) != 0;
                mAppVisible = (res & WindowManagerGlobal.ADD_FLAG_APP_VISIBLE) != 0;

                if (mAccessibilityManager.isEnabled()) {
                    mAccessibilityInteractionConnectionManager.ensureConnection();
                }

                if (view.getImportantForAccessibility() == View.IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
                    view.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
                }

                // Set up the input pipeline.
                CharSequence counterSuffix = attrs.getTitle();
                mSyntheticInputStage = new SyntheticInputStage();
                InputStage viewPostImeStage = new ViewPostImeInputStage(mSyntheticInputStage);
                InputStage nativePostImeStage = new NativePostImeInputStage(viewPostImeStage,
                        "aq:native-post-ime:" + counterSuffix);
                InputStage earlyPostImeStage = new EarlyPostImeInputStage(nativePostImeStage);
                InputStage imeStage = new ImeInputStage(earlyPostImeStage,
                        "aq:ime:" + counterSuffix);
                InputStage viewPreImeStage = new ViewPreImeInputStage(imeStage);
                InputStage nativePreImeStage = new NativePreImeInputStage(viewPreImeStage,
                        "aq:native-pre-ime:" + counterSuffix);

                mFirstInputStage = nativePreImeStage;
                mFirstPostImeInputStage = earlyPostImeStage;
                mPendingInputEventQueueLengthCounterName = "aq:pending:" + counterSuffix;
            }
        }
    }

通过前面的分析可以知道,用户自定义的UI作为一个子View被添加到DecorView中,然后将顶级视图DecorView添加到应用程序进程的窗口管理器中,窗口管理器首先为当前添加的View创建一个ViewRootImpl对象、一个布局参数对象ViewGroup.LayoutParams,然后将这三个对象分别保存到当前应用程序进程的窗口管理器WindowManagerImpl中,最后通过ViewRootImpl对象将当前视图对象注册到WMS服务中。

ViewRootImpl的setView函数向WMS服务添加一个窗口对象过程:

(1) requestLayout()在应用程序进程中进行窗口UI布局;

(2) WindowSession.addToDisplay()向WMS服务注册一个窗口对象;

(3) 注册应用程序进程端的消息接收通道;

5.2.1、窗口UI布局过程 ViewRootImpl.requestLayout()

requestLayout函数调用里面使用了Hanlder的一个小手段,那就是利用postSyncBarrier添加了一个Barrier(挡板),这个挡板的作用是阻塞普通的同步消息的执行,在挡板被撤销之前,只会执行异步消息,而requestLayout先添加了一个挡板Barrier,之后自己插入了一个异步任务mTraversalRunnable,其主要作用就是保证mTraversalRunnable在所有同步Message之前被执行,保证View绘制的最高优先级。具体实现如下:

G:\android9.0\frameworks\base\core\java\android\view\ViewRootImpl.java
Override
public void requestLayout() {
    if (!mHandlingLayoutInLayoutRequest) {
        checkThread();
        mLayoutRequested = true;
        scheduleTraversals();
    }
}

final class TraversalRunnable implements Runnable {
    @Override
    public void run() {
        doTraversal();
    }
}
final TraversalRunnable mTraversalRunnable = new TraversalRunnable();


void scheduleTraversals() {
    if (!mTraversalScheduled) {
        mTraversalScheduled = true;
        mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
        mChoreographer.postCallback(
                Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
        if (!mUnbufferedInputDispatch) {
            scheduleConsumeBatchedInput();
        }
        notifyRendererOfFramePending();
        pokeDrawLockIfNeeded();
    }
}
5.2.2、添加回调过程 mChoreographer.postCallback()
G:\android9.0\frameworks\base\core\java\android\view\Choreographer.java

    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) {
        if (DEBUG_FRAMES) {
            Log.d(TAG, "PostCallback: type=" + callbackType
                    + ", action=" + action + ", token=" + token
                    + ", delayMillis=" + delayMillis);
        }

        synchronized (mLock) {
            final long now = SystemClock.uptimeMillis();
            final long dueTime = now + delayMillis;
           //将要执行的回调封装成CallbackRecord对象,保存到mCallbackQueues数组中
            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);
            }
        }
    }


     scheduleFrameLocked(long now) {
        if (!mFrameScheduled) {
            mFrameScheduled = true;
            ......
            if (USE_VSYNC) {
                if (DEBUG_FRAMES) {
                    Log.d(TAG, "Scheduling next frame on vsync.");
                }

                // If running on the Looper thread, then schedule the vsync immediately,
                // otherwise post a message to schedule the vsync from the UI thread
                // as soon as possible.
                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);
            }
        }
    }

消息处理:

G:\android9.0\frameworks\base\core\java\android\view\Choreographer.java
    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);
                    break;
                case MSG_DO_SCHEDULE_VSYNC:
                    doScheduleVsync();
                    break;
                case MSG_DO_SCHEDULE_CALLBACK:
                    doScheduleCallback(msg.arg1);
                    break;
            }
        }
    }
    void doScheduleVsync() {
        synchronized (mLock) {
            if (mFrameScheduled) {
                scheduleVsyncLocked();
            }
        }
    }
    private void scheduleVsyncLocked() {
        mDisplayEventReceiver.scheduleVsync();
    }

在该函数中考虑了两种情况,一种是系统没有使用Vsync机制,在这种情况下,首先根据屏幕刷新频率计算下一次刷新时间,通过异步消息方式延时执行doFrame()函数实现屏幕刷新。如果系统使用了Vsync机制,并且当前线程具备消息循环,则直接请求Vsync信号,否则就通过主线程来请求Vsync信号。

5.2.3、Vsync请求过程 mDisplayEventReceiver.scheduleVsync()

我们知道在Choreographer构造函数中,构造了一个FrameDisplayEventReceiver对象,用于请求并接收Vsync信号,Vsync信号请求过程如下:

G:\android9.0\frameworks\base\core\java\android\view\DisplayEventReceiver.java
    public void scheduleVsync() {
        if (mReceiverPtr == 0) {
            Log.w(TAG, "Attempted to schedule a vertical sync pulse but the display event "
                    + "receiver has already been disposed.");
        } else {
            nativeScheduleVsync(mReceiverPtr);
        }
    }
G:\android9.0\frameworks\base\core\jni\android_view_DisplayEventReceiver.cpp
static void nativeScheduleVsync(JNIEnv* env, jclass clazz, jlong receiverPtr) {
    sp<NativeDisplayEventReceiver> receiver =
            reinterpret_cast<NativeDisplayEventReceiver*>(receiverPtr);
    status_t status = receiver->scheduleVsync();
    if (status) {
        String8 message;
        message.appendFormat("Failed to schedule next vertical sync pulse.  status=%d", status);
        jniThrowRuntimeException(env, message.string());
    }
}

VSync请求过程又转交给了DisplayEventDispatcher: [->DisplayEventDispatcher.cpp]

G:\android9.0\frameworks\base\libs\androidfw\DisplayEventDispatcher.cpp

status_t DisplayEventDispatcher::scheduleVsync() {
    if (!mWaitingForVsync) {
        ALOGV("dispatcher %p ~ Scheduling vsync.", this);

        // Drain all pending events.
        nsecs_t vsyncTimestamp;
        int32_t vsyncDisplayId;
        uint32_t vsyncCount;
        //处理显示设备插入
        if (processPendingEvents(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount)) {
            ALOGE("dispatcher %p ~ last event processed while scheduling was for %" PRId64 "",
                    this, ns2ms(static_cast<nsecs_t>(vsyncTimestamp)));
        }

        status_t status = mReceiver.requestNextVsync();
        if (status) {
            ALOGW("Failed to request next vsync, status=%d", status);
            return status;
        }

        mWaitingForVsync = true;
    }
    return OK;
}

VSync请求过程又转交给了DisplayEventReceiver: [->DisplayEventReceiver.cpp]

G:\android9.0\frameworks\native\libs\gui\DisplayEventReceiver.cpp
status_t DisplayEventReceiver::requestNextVsync() {
    if (mEventConnection != NULL) {
        mEventConnection->requestNextVsync();
        return NO_ERROR;
    }
    return NO_INIT;
}

看服务端的实现

G:\android9.0\frameworks\native\services\surfaceflinger\EventThread.cpp

void EventThread::requestNextVsync(const sp<EventThread::Connection>& connection) {
    std::lock_guard<std::mutex> lock(mMutex);

    if (mResyncWithRateLimitCallback) {
        mResyncWithRateLimitCallback();
    }

    if (connection->count < 0) {
        connection->count = 0;
        mCondition.notify_all();
    }
}


void EventThread::threadMain() NO_THREAD_SAFETY_ANALYSIS {
    std::unique_lock<std::mutex> lock(mMutex);
    while (mKeepRunning) {
        DisplayEventReceiver::Event event;
        Vector<sp<EventThread::Connection> > signalConnections;
        signalConnections = waitForEventLocked(&lock, &event);

        // dispatch events to listeners...
        const size_t count = signalConnections.size();
        for (size_t i = 0; i < count; i++) {
            const sp<Connection>& conn(signalConnections[i]);
            // now see if we still need to report this event
            status_t err = conn->postEvent(event);
            if (err == -EAGAIN || err == -EWOULDBLOCK) {
                // The destination doesn't accept events anymore, it's probably
                // full. For now, we just drop the events on the floor.
                // FIXME: Note that some events cannot be dropped and would have
                // to be re-sent later.
                // Right-now we don't have the ability to do this.
                ALOGW("EventThread: dropping event (%08x) for connection %p", event.header.type,
                      conn.get());
            } else if (err < 0) {
                // handle any other error on the pipe as fatal. the only
                // reasonable thing to do is to clean-up this connection.
                // The most common error we'll get here is -EPIPE.
                removeDisplayEventConnectionLocked(signalConnections[i]);
            }
        }
    }
}

waitForEventLocked()函数中等待下一个VSYNC的trigger.。

需要说明的是

/**Vsync start**/
/**Vsync end**/
之间的代码此时其实还未执行,call requestNextVsync()来告诉系统我要在下一个VSYNC需要被trigger.

继续ViewRootImpl的setView函数中的WindowSession.addToDisplay()。

5.3、mWindowSession.addToDisplay()向WMS服务注册一个窗口对象
G:\android9.0\frameworks\base\services\core\java\com\android\server\wm\Session.java

Override
public int addToDisplay(IWindow window, int seq, WindowManager.LayoutParams attrs,
        int viewVisibility, int displayId, Rect outFrame, Rect outContentInsets,
        Rect outStableInsets, Rect outOutsets,
        DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel) {
    return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId, outFrame,
            outContentInsets, outStableInsets, outOutsets, outDisplayCutout, outInputChannel);
}

看看WindowManagerService.java的addWindow()实现

5.3.1、WindowManagerService.addWindow()
G:\android9.0\frameworks\base\services\core\java\com\android\server\wm\WindowManagerService.java


    public int addWindow(Session session, IWindow client, int seq,
            LayoutParams attrs, int viewVisibility, int displayId, Rect outFrame,
            Rect outContentInsets, Rect outStableInsets, Rect outOutsets,
            DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel) {
        int[] appOp = new int[1];
        ......

        boolean reportNewConfig = false;
        WindowState parentWindow = null;
        long origId;
        final int callingUid = Binder.getCallingUid();
        final int type = attrs.type;

        mFocusingActivity = attrs.getTitle().toString();

        synchronized(mWindowMap) {
            .......
            final DisplayContent displayContent = getDisplayContentOrCreate(displayId);

            ......

            AppWindowToken atoken = null;
            final boolean hasParent = parentWindow != null;
            // Use existing parent window token for child windows since they go in the same token
            // as there parent window so we can apply the same policy on them.
            WindowToken token = displayContent.getWindowToken(
                    hasParent ? parentWindow.mAttrs.token : attrs.token);
            // If this is a child window, we want to apply the same type checking rules as the
            // parent window type.
            final int rootType = hasParent ? parentWindow.mAttrs.type : type;

            boolean addToastWindowRequiresToken = false;

            if (token == null) {
                .......
                final IBinder binder = attrs.token != null ? attrs.token : client.asBinder();
                final boolean isRoundedCornerOverlay =
                        (attrs.privateFlags & PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY) != 0;
                token = new WindowToken(this, binder, type, false, displayContent,
                        session.mCanAddInternalSystemWindow, isRoundedCornerOverlay);
            } ......
            } else if (token.asAppWindowToken() != null) {
                Slog.w(TAG_WM, "Non-null appWindowToken for system window of rootType=" + rootType);
                // It is not valid to use an app token with other system types; we will
                // instead make a new token for it (as if null had been passed in for the token).
                attrs.token = null;
                token = new WindowToken(this, client.asBinder(), type, false, displayContent,
                        session.mCanAddInternalSystemWindow);
            }

            final WindowState win = new WindowState(this, session, client, token, parentWindow,
                    appOp[0], seq, attrs, viewVisibility, session.mUid,
                    session.mCanAddInternalSystemWindow);
            ......

            final boolean hasStatusBarServicePermission =
                    mContext.checkCallingOrSelfPermission(permission.STATUS_BAR_SERVICE)
                            == PackageManager.PERMISSION_GRANTED;
            mPolicy.adjustWindowParamsLw(win, win.mAttrs, hasStatusBarServicePermission);
            win.setShowToOwnerOnlyLocked(mPolicy.checkShowToOwnerOnly(attrs));

            res = mPolicy.prepareAddWindowLw(win, attrs);
            ......

            final boolean openInputChannels = (outInputChannel != null
                    && (attrs.inputFeatures & INPUT_FEATURE_NO_INPUT_CHANNEL) == 0);
            if  (openInputChannels) {
                win.openInputChannel(outInputChannel);
            }

            ......

            res = WindowManagerGlobal.ADD_OKAY;
            ......
            origId = Binder.clearCallingIdentity();

            win.attach();
            //将win加入到mWindowMap中
            mWindowMap.put(client.asBinder(), win);

            win.initAppOpsState();

            final boolean suspended = mPmInternal.isPackageSuspended(win.getOwningPackage(),
                    UserHandle.getUserId(win.getOwningUid()));
            win.setHiddenWhileSuspended(suspended);

            final boolean hideSystemAlertWindows = !mHidingNonSystemOverlayWindows.isEmpty();
            win.setForceHideNonSystemOverlayWindowIfNeeded(hideSystemAlertWindows);

            final AppWindowToken aToken = token.asAppWindowToken();
            if (type == TYPE_APPLICATION_STARTING && aToken != null) {
                aToken.startingWindow = win;
                if (DEBUG_STARTING_WINDOW) Slog.v (TAG_WM, "addWindow: " + aToken
                        + " startingWindow=" + win);
            }

            boolean imMayMove = true;
            //将win加入到mToken中
            win.mToken.addWindow(win);

            if (type == TYPE_INPUT_METHOD) {
                win.mGivenInsetsPending = true;
                setInputMethodWindowLocked(win);
                imMayMove = false;
            } else if (type == TYPE_INPUT_METHOD_DIALOG) {
                displayContent.computeImeTarget(true /* updateImeTarget */);
                imMayMove = false;
            } else {
                if (type == TYPE_WALLPAPER) {
                    displayContent.mWallpaperController.clearLastWallpaperTimeoutTime();
                    displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
                } else if ((attrs.flags&FLAG_SHOW_WALLPAPER) != 0) {
                    displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
                } else if (displayContent.mWallpaperController.isBelowWallpaperTarget(win)) {
                    // If there is currently a wallpaper being shown, and
                    // the base layer of the new window is below the current
                    // layer of the target window, then adjust the wallpaper.
                    // This is to avoid a new window being placed between the
                    // wallpaper and its target.
                    displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
                }
            }

            // If the window is being added to a stack that's currently adjusted for IME,
            // make sure to apply the same adjust to this new window.
            win.applyAdjustForImeIfNeeded();

            if (type == TYPE_DOCK_DIVIDER) {
                mRoot.getDisplayContent(displayId).getDockedDividerController().setWindow(win);
            }

            final WindowStateAnimator winAnimator = win.mWinAnimator;
            winAnimator.mEnterAnimationPending = true;
            winAnimator.mEnteringAnimation = true;
            // Check if we need to prepare a transition for replacing window first.
            if (atoken != null && atoken.isVisible()
                    && !prepareWindowReplacementTransition(atoken)) {
                // If not, check if need to set up a dummy transition during display freeze
                // so that the unfreeze wait for the apps to draw. This might be needed if
                // the app is relaunching.
                prepareNoneTransitionForRelaunching(atoken);
            }

            final DisplayFrames displayFrames = displayContent.mDisplayFrames;
            // TODO: Not sure if onDisplayInfoUpdated() call is needed.
            final DisplayInfo displayInfo = displayContent.getDisplayInfo();
            displayFrames.onDisplayInfoUpdated(displayInfo,
                    displayContent.calculateDisplayCutoutForRotation(displayInfo.rotation));
            final Rect taskBounds;
            if (atoken != null && atoken.getTask() != null) {
                taskBounds = mTmpRect;
                atoken.getTask().getBounds(mTmpRect);
            } else {
                taskBounds = null;
            }
            if (mPolicy.getLayoutHintLw(win.mAttrs, taskBounds, displayFrames, outFrame,
                    outContentInsets, outStableInsets, outOutsets, outDisplayCutout)) {
                res |= WindowManagerGlobal.ADD_FLAG_ALWAYS_CONSUME_NAV_BAR;
            }

            if (mInTouchMode) {
                res |= WindowManagerGlobal.ADD_FLAG_IN_TOUCH_MODE;
            }
            if (win.mAppToken == null || !win.mAppToken.isClientHidden()) {
                res |= WindowManagerGlobal.ADD_FLAG_APP_VISIBLE;
            }

            mInputMonitor.setUpdateInputWindowsNeededLw();

            boolean focusChanged = false;
            if (win.canReceiveKeys()) {
                focusChanged = updateFocusedWindowLocked(UPDATE_FOCUS_WILL_ASSIGN_LAYERS,
                        false /*updateInputWindows*/);
                if (focusChanged) {
                    imMayMove = false;
                }
            }

            if (imMayMove) {
                displayContent.computeImeTarget(true /* updateImeTarget */);
            }

            // Don't do layout here, the window must call
            // relayout to be displayed, so we'll do it there.
            win.getParent().assignChildLayers();

            if (focusChanged) {
                mInputMonitor.setInputFocusLw(mCurrentFocus, false /*updateInputWindows*/);
            }
----------------------------------------------------------------
对应Log:
04-16 13:08:36.967 D/WindowManager( 1049): addInputWindowHandle: Window{c1255cd u0 com.android.testred/com.android.testred.TestActivity}, Window{c1255cd u0 com.android.testred/com.android.testred.TestActivity}, layer=0, frame=[0,0,0,0], touchableRegion=SkRegion((0,0,480,854)), visible=false
----------------------------------------------------------------

            mInputMonitor.updateInputWindowsLw(false /*force*/);
----------------------------------------------------------------
对应Log:
04-16 13:08:36.968 V/WindowManager( 1049): addWindow: New client android.os.BinderProxy@b9baf64: window=Window{c1255cd u0 com.android.testred/com.android.testred.TestActivity} Callers=com.android.server.wm.Session.addToDisplay:205 android.view.IWindowSession$Stub.onTransact:129 com.android.server.wm.Session.onTransact:164 android.os.Binder.execTransact:731 <bottom of call stack> 

----------------------------------------------------------------


            if (localLOGV || DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "addWindow: New client "
                    + client.asBinder() + ": window=" + win + " Callers=" + Debug.getCallers(5));

            if (win.isVisibleOrAdding() && updateOrientationFromAppTokensLocked(displayId)) {
                reportNewConfig = true;
            }
        }

        if (reportNewConfig) {
            sendNewConfiguration(displayId);
        }

        Binder.restoreCallingIdentity(origId);

        return res;
    }
5.3.1.1、WindowState创建
G:\android9.0\frameworks\base\services\core\java\com\android\server\wm\WindowState.java

    WindowState(WindowManagerService service, Session s, IWindow c, WindowToken token,
            WindowState parentWindow, int appOp, int seq, WindowManager.LayoutParams a,
            int viewVisibility, int ownerId, boolean ownerCanAddInternalSystemWindow,
            PowerManagerWrapper powerManagerWrapper) {
        super(service);
        mSession = s;
        mClient = c;
        mAppOp = appOp;
        mToken = token;
        mAppToken = mToken.asAppWindowToken();
        mOwnerUid = ownerId;
        mOwnerCanAddInternalSystemWindow = ownerCanAddInternalSystemWindow;
        mWindowId = new WindowId(this);
        mAttrs.copyFrom(a);
        mLastSurfaceInsets.set(mAttrs.surfaceInsets);
        mViewVisibility = viewVisibility;
        mPolicy = mService.mPolicy;
        mContext = mService.mContext;
        DeathRecipient deathRecipient = new DeathRecipient();
        mSeq = seq;
        mEnforceSizeCompat = (mAttrs.privateFlags & PRIVATE_FLAG_COMPATIBLE_WINDOW) != 0;
        mPowerManagerWrapper = powerManagerWrapper;
----------------------------------------------------------------
对应Log:
04-16 13:08:36.964 V/WindowState( 1049): Window Window{c1255cd u0 com.android.testred/com.android.testred.TestActivity} client=android.os.BinderProxy@b9baf64 token=AppWindowToken{1579134 token=Token{ce2ac07 ActivityRecord{65cc87a u0 com.android.testred/.TestActivity t5}}} (Token{ce2ac07 ActivityRecord{65cc87a u0 com.android.testred/.TestActivity t5}}) params={(0,0)(fillxfill) sim={forwardNavigation} ty=BASE_APPLICATION fmt=TRANSPARENT wanim=0x1030000
04-16 13:08:36.964 V/WindowState( 1049):   fl=LAYOUT_IN_SCREEN LAYOUT_INSET_DECOR SPLIT_TOUCH HARDWARE_ACCELERATED}

----------------------------------------------------------------
        if (localLOGV) Slog.v(
            TAG, "Window " + this + " client=" + c.asBinder()
            + " token=" + token + " (" + mAttrs.token + ")" + " params=" + a);
        try {
            c.asBinder().linkToDeath(deathRecipient, 0);
        } catch (RemoteException e) {
            mDeathRecipient = null;
            mIsChildWindow = false;
            mLayoutAttached = false;
            mIsImWindow = false;
            mIsWallpaper = false;
            mIsFloatingLayer = false;
            mBaseLayer = 0;
            mSubLayer = 0;
            mInputWindowHandle = null;
            mWinAnimator = null;
            return;
        }
        mDeathRecipient = deathRecipient;

    //zhoujinjian start
    if("com.android.testred".equals(mAttrs.packageName) 
            || "com.android.testgreen".equals(mAttrs.packageName)
            || "com.android.testblue".equals(mAttrs.packageName)){
            mBaseLayer = 21010;
            mSubLayer = 0;
            mIsChildWindow = false;
            mLayoutAttached = false;
            mIsImWindow = mAttrs.type == TYPE_INPUT_METHOD
                    || mAttrs.type == TYPE_INPUT_METHOD_DIALOG;
            mIsWallpaper = mAttrs.type == TYPE_WALLPAPER;
    } else{

            if (mAttrs.type >= FIRST_SUB_WINDOW && mAttrs.type <= LAST_SUB_WINDOW) {
                // The multiplier here is to reserve space for multiple
                // windows in the same type layer.
                mBaseLayer = mPolicy.getWindowLayerLw(parentWindow)
                        * TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET;
                mSubLayer = mPolicy.getSubWindowLayerFromTypeLw(a.type);
                mIsChildWindow = true;

                if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + this + " to " + parentWindow);
                parentWindow.addChild(this, sWindowSubLayerComparator);

                mLayoutAttached = mAttrs.type !=
                        WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
                mIsImWindow = parentWindow.mAttrs.type == TYPE_INPUT_METHOD
                        || parentWindow.mAttrs.type == TYPE_INPUT_METHOD_DIALOG;
                mIsWallpaper = parentWindow.mAttrs.type == TYPE_WALLPAPER;
            } else {
                // The multiplier here is to reserve space for multiple
                // windows in the same type layer.
                mBaseLayer = mPolicy.getWindowLayerLw(this)
                        * TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET;
                mSubLayer = 0;
                mIsChildWindow = false;
                mLayoutAttached = false;
                mIsImWindow = mAttrs.type == TYPE_INPUT_METHOD
                        || mAttrs.type == TYPE_INPUT_METHOD_DIALOG;
                mIsWallpaper = mAttrs.type == TYPE_WALLPAPER;
            }

    }
     //zhoujinjian end

        mIsFloatingLayer = mIsImWindow || mIsWallpaper;

        if (mAppToken != null && mAppToken.mShowForAllUsers) {
            // Windows for apps that can show for all users should also show when the device is
            // locked.
            mAttrs.flags |= FLAG_SHOW_WHEN_LOCKED;
        }
        //创建WindowStateAnimator
        mWinAnimator = new WindowStateAnimator(this);
        mWinAnimator.mAlpha = a.alpha;

        mRequestedWidth = 0;
        mRequestedHeight = 0;
        mLastRequestedWidth = 0;
        mLastRequestedHeight = 0;
        mLayer = 0;
        mInputWindowHandle = new InputWindowHandle(
                mAppToken != null ? mAppToken.mInputApplicationHandle : null, this, c,
                    getDisplayId());
    }
5.3.1.2、WindowState.attach()

在WMS服务端创建了所需对象后,接着调用了WindowState的attach()来进一步完成窗口添加。

G:\android9.0\frameworks\base\services\core\java\com\android\server\wm\WindowState.java

----------------------------------------------------------------
对应Log:
04-16 13:08:36.964 V/WindowState( 1049): Attaching Window{c1255cd u0 com.android.testred/com.android.testred.TestActivity} token=AppWindowToken{1579134 token=Token{ce2ac07 ActivityRecord{65cc87a u0 com.android.testred/.TestActivity t5}}}
----------------------------------------------------------------

    void attach() {
        if (localLOGV) Slog.v(TAG, "Attaching " + this + " token=" + mToken);
        mSession.windowAddedLocked(mAttrs.packageName);
    }
5.3.1.3、mSession.windowAddedLocked(mAttrs.packageName)
G:\android9.0\frameworks\base\services\core\java\com\android\server\wm\Session.java

    void windowAddedLocked(String packageName) {
        mPackageName = packageName;
        mRelayoutTag = "relayoutWindow: " + mPackageName;
        if (mSurfaceSession == null) {

----------------------------------------------------------------
对应Log:

04-16 13:08:36.964 V/WindowManager( 1049): First window added to Session{e6e78f6 2602:u0a10088}, creating SurfaceSession
04-16 13:08:36.965 I/WindowManager( 1049):   NEW SURFACE SESSION android.view.SurfaceSession@3812e82
----------------------------------------------------------------
            if (WindowManagerService.localLOGV) Slog.v(
                TAG_WM, "First window added to " + this + ", creating SurfaceSession");
            mSurfaceSession = new SurfaceSession();
            if (SHOW_TRANSACTIONS) Slog.i(
                    TAG_WM, "  NEW SURFACE SESSION " + mSurfaceSession);
            mService.mSessions.add(this);
            if (mLastReportedAnimatorScale != mService.getCurrentAnimatorScale()) {
                mService.dispatchNewAnimatorScaleLocked(this);
            }
        }
        mNumWindow++;
    }
5.3.1.4、SurfaceSession建立过程

SurfaceSession对象承担了应用程序与SurfaceFlinger之间的通信过程,每一个需要与SurfaceFlinger进程交互的应用程序端都需要创建一个SurfaceSession对象。

客户端请求

G:\android9.0\frameworks\base\core\java\android\view\SurfaceSession.java

/**
 * An instance of this class represents a connection to the surface
 * flinger, from which you can create one or more Surface instances that will
 * be composited to the screen.
 * {@hide}
 */
public final class SurfaceSession {
    // Note: This field is accessed by native code.
    private long mNativeClient; // SurfaceComposerClient*

    /** Create a new connection with the surface flinger. */
    public SurfaceSession() {
        mNativeClient = nativeCreate();
    }
    ......
}

Java层的SurfaceSession对象构造过程会通过JNI在native层创建一个SurfaceComposerClient对象。

G:\android9.0\frameworks\base\core\jni\android_view_SurfaceSession.cpp

static jlong nativeCreate(JNIEnv* env, jclass clazz) {
    SurfaceComposerClient* client = new SurfaceComposerClient();
    client->incStrong((void*)nativeCreate);
    return reinterpret_cast<jlong>(client);
}

Java层的SurfaceSession对象与C++层的SurfaceComposerClient对象之间是一对一关系。

G:\android9.0\frameworks\native\libs\gui\SurfaceComposerClient.cpp

SurfaceComposerClient::SurfaceComposerClient()
    : mStatus(NO_INIT)
{
}

void SurfaceComposerClient::onFirstRef() {
    sp<ISurfaceComposer> sf(ComposerService::getComposerService());
    if (sf != 0 && mStatus == NO_INIT) {
        auto rootProducer = mParent.promote();
        sp<ISurfaceComposerClient> conn;
        conn = (rootProducer != nullptr) ? sf->createScopedConnection(rootProducer) :
                sf->createConnection();
        if (conn != 0) {
            mClient = conn;
            mStatus = NO_ERROR;
        }
    }
}

SurfaceComposerClient继承于RefBase类,当第一次被强引用时,onFirstRef函数被回调,在该函数中SurfaceComposerClient会请求SurfaceFlinger为当前应用程序创建一个Client对象,专门接收该应用程序的请求,在SurfaceFlinger端创建好Client本地Binder对象后,将该Binder代理对象返回给应用程序端,并保存在SurfaceComposerClient的成员变量mClient中。

服务端处理 在SurfaceFlinger服务端为应用程序创建交互的Client对象 [SurfaceFlinger.cpp]

G:\android9.0\frameworks\native\services\surfaceflinger\SurfaceFlinger.cpp


sp<ISurfaceComposerClient> SurfaceFlinger::createConnection() {
    return initClient(new Client(this));
}

sp<ISurfaceComposerClient> SurfaceFlinger::createScopedConnection(
        const sp<IGraphicBufferProducer>& gbp) {
    if (authenticateSurfaceTexture(gbp) == false) {
        return nullptr;
    }
    const auto& layer = (static_cast<MonitoredProducer*>(gbp.get()))->getLayer();
    if (layer == nullptr) {
        return nullptr;
    }

   return initClient(new Client(this, layer));
}

enter image description here

5.3.1.5、win.mToken.addWindow(win)
G:\android9.0\frameworks\base\services\core\java\com\android\server\wm\WindowToken.java
----------------------------------------------------------------
对应Log:
04-16 13:08:36.965 D/WindowManager( 1049): addWindow: win=Window{c1255cd u0 com.android.testred/com.android.testred.TestActivity} Callers=com.android.server.wm.AppWindowToken.addWindow:989 com.android.server.wm.WindowManagerService.addWindow:1426 com.android.server.wm.Session.addToDisplay:205 android.view.IWindowSession$Stub.onTransact:129 com.android.server.wm.Session.onTransact:164 
04-16 13:08:36.965 V/WindowManager( 1049): Adding Window{c1255cd u0 com.android.testred/com.android.testred.TestActivity} to AppWindowToken{1579134 token=Token{ce2ac07 ActivityRecord{65cc87a u0 com.android.testred/.TestActivity t5}}}
----------------------------------------------------------------
    void addWindow(final WindowState win) {
        if (DEBUG_FOCUS) Slog.d(TAG_WM,
                "addWindow: win=" + win + " Callers=" + Debug.getCallers(5));

        if (win.isChildWindow()) {
            // Child windows are added to their parent windows.
            return;
        }
        if (!mChildren.contains(win)) {
            if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "Adding " + win + " to " + this);
            addChild(win, mWindowComparator);
            mService.mWindowsChanged = true;
            // TODO: Should we also be setting layout needed here and other places?
        }
    }

/**Vsync start**/

(二)、Vsync trigger

(1)、DisplayEventReceiver::sendEvents
G:\android9.0\frameworks\native\services\surfaceflinger\EventThread.cpp

void EventThread::threadMain() NO_THREAD_SAFETY_ANALYSIS {
    std::unique_lock<std::mutex> lock(mMutex);
    while (mKeepRunning) {
        DisplayEventReceiver::Event event;
        Vector<sp<EventThread::Connection> > signalConnections;
        signalConnections = waitForEventLocked(&lock, &event);

        // dispatch events to listeners...
        const size_t count = signalConnections.size();
        for (size_t i = 0; i < count; i++) {
            const sp<Connection>& conn(signalConnections[i]);
            // now see if we still need to report this event
            status_t err = conn->postEvent(event);
            if (err == -EAGAIN || err == -EWOULDBLOCK) {
                // The destination doesn't accept events anymore, it's probably
                // full. For now, we just drop the events on the floor.
                // FIXME: Note that some events cannot be dropped and would have
                // to be re-sent later.
                // Right-now we don't have the ability to do this.
                ALOGW("EventThread: dropping event (%08x) for connection %p", event.header.type,
                      conn.get());
            } else if (err < 0) {
                // handle any other error on the pipe as fatal. the only
                // reasonable thing to do is to clean-up this connection.
                // The most common error we'll get here is -EPIPE.
                removeDisplayEventConnectionLocked(signalConnections[i]);
            }
        }
    }
}


status_t EventThread::Connection::postEvent(const DisplayEventReceiver::Event& event) {
    ssize_t size = DisplayEventReceiver::sendEvents(&mChannel, &event, 1);
    return size < 0 ? status_t(size) : status_t(NO_ERROR);
}

当有Vsync信号来到时,会调用conn->postEvent(event)。

G:\android9.0\frameworks\native\libs\gui\DisplayEventReceiver.cpp

ssize_t DisplayEventReceiver::sendEvents(gui::BitTube* dataChannel,
        Event const* events, size_t count)
{
    return gui::BitTube::sendObjects(dataChannel, events, count);
}


G:\android9.0\frameworks\native\libs\sensor\BitTube.cpp

ssize_t BitTube::sendObjects(const sp<BitTube>& tube,
        void const* events, size_t count, size_t objSize)
{
    const char* vaddr = reinterpret_cast<const char*>(events);
    ssize_t size = tube->write(vaddr, count*objSize);

    // should never happen because of SOCK_SEQPACKET
    LOG_ALWAYS_FATAL_IF((size >= 0) && (size % static_cast<ssize_t>(objSize)),
            "BitTube::sendObjects(count=%zu, size=%zu), res=%zd (partial events were sent!)",
            count, objSize, size);

    //ALOGE_IF(size<0, "error %d sending %d events", size, count);
    return size < 0 ? size : size / static_cast<ssize_t>(objSize);
}

ssize_t BitTube::write(void const* vaddr, size_t size)
{
    ssize_t err, len;
    do {
        len = ::send(mSendFd, vaddr, size, MSG_DONTWAIT | MSG_NOSIGNAL);
        // cannot return less than size, since we're using SOCK_SEQPACKET
        err = len < 0 ? errno : 0;
    } while (err == EINTR);
    return err == 0 ? len : -err;
}

从BitTube的初始化函数可以看出使用了套接来通讯

G:\android9.0\frameworks\native\libs\sensor\BitTube.cpp

void BitTube::init(size_t rcvbuf, size_t sndbuf) {
    int sockets[2];
    if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sockets) == 0) {
        size_t size = DEFAULT_SOCKET_BUFFER_SIZE;
        setsockopt(sockets[0], SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf));
        setsockopt(sockets[1], SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf));
        // sine we don't use the "return channel", we keep it small...
        setsockopt(sockets[0], SOL_SOCKET, SO_SNDBUF, &size, sizeof(size));
        setsockopt(sockets[1], SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));
        fcntl(sockets[0], F_SETFL, O_NONBLOCK);
        fcntl(sockets[1], F_SETFL, O_NONBLOCK);
        mReceiveFd = sockets[0];
        mSendFd = sockets[1];
    } else {
        mReceiveFd = -errno;
        ALOGE("BitTube: pipe creation failed (%s)", strerror(-mReceiveFd));
    }
}
G:\android9.0\frameworks\native\libs\sensor\BitTube.cpp
ssize_t BitTube::recvObjects(BitTube* tube, void* events, size_t count, size_t objSize) {
    char* vaddr = reinterpret_cast<char*>(events);
    ssize_t size = tube->read(vaddr, count * objSize);

    // should never happen because of SOCK_SEQPACKET
    LOG_ALWAYS_FATAL_IF((size >= 0) && (size % static_cast<ssize_t>(objSize)),
                        "BitTube::recvObjects(count=%zu, size=%zu), res=%zd (partial events were "
                        "received!)",
                        count, objSize, size);

    // ALOGE_IF(size<0, "error %d receiving %d events", size, count);
    return size < 0 ? size : size / static_cast<ssize_t>(objSize);
}
G:\android9.0\frameworks\native\libs\sensor\BitTube.cpp
ssize_t BitTube::read(void* vaddr, size_t size) {
    ssize_t err, len;
    do {
        len = ::recv(mReceiveFd, vaddr, size, MSG_DONTWAIT);
        err = len < 0 ? errno : 0;
    } while (err == EINTR);
    if (err == EAGAIN || err == EWOULDBLOCK) {
        // EAGAIN means that we have non-blocking I/O but there was no data to be read. Nothing the
        // client should care about.
        return 0;
    }
    return err == 0 ? len : -err;
}
(2)、DisplayEventDispatcher::handleEvent
G:\android9.0\frameworks\base\libs\androidfw\DisplayEventDispatcher.cpp

DisplayEventDispatcher::DisplayEventDispatcher(const sp<Looper>& looper,
        ISurfaceComposer::VsyncSource vsyncSource) :
        mLooper(looper), mReceiver(vsyncSource), mWaitingForVsync(false) {
    ALOGV("dispatcher %p ~ Initializing display event dispatcher.", this);
}

status_t DisplayEventDispatcher::initialize() {
    status_t result = mReceiver.initCheck();
    if (result) {
        ALOGW("Failed to initialize display event receiver, status=%d", result);
        return result;
    }

    int rc = mLooper->addFd(mReceiver.getFd(), 0, Looper::EVENT_INPUT,
            this, NULL);
    if (rc < 0) {
        return UNKNOWN_ERROR;
    }
    return OK;
}

而最终在addFd中注册的回调时this,这个我们之前在分析Looper的时候分析过,也就是会调用这个类的handleEvent函数,在这个函数中调用dispatchVsync继续分发VSync信号。

G:\android9.0\frameworks\base\libs\androidfw\DisplayEventDispatcher.cpp

int DisplayEventDispatcher::handleEvent(int, int events, void*) {
    if (events & (Looper::EVENT_ERROR | Looper::EVENT_HANGUP)) {
        ALOGE("Display event receiver pipe was closed or an error occurred.  "
                "events=0x%x", events);
        return 0; // remove the callback
    }

    if (!(events & Looper::EVENT_INPUT)) {
        ALOGW("Received spurious callback for unhandled poll event.  "
                "events=0x%x", events);
        return 1; // keep the callback
    }

    // Drain all pending events, keep the last vsync.
    nsecs_t vsyncTimestamp;
    int32_t vsyncDisplayId;
    uint32_t vsyncCount;
    if (processPendingEvents(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount)) {
        ALOGV("dispatcher %p ~ Vsync pulse: timestamp=%" PRId64 ", id=%d, count=%d",
                this, ns2ms(vsyncTimestamp), vsyncDisplayId, vsyncCount);
        mWaitingForVsync = false;
        dispatchVsync(vsyncTimestamp, vsyncDisplayId, vsyncCount);
    }

    return 1; // keep the callback
}
G:\android9.0\frameworks\base\core\jni\android_view_DisplayEventReceiver.cpp

void NativeDisplayEventReceiver::dispatchVsync(nsecs_t timestamp, int32_t id, uint32_t count) {
    JNIEnv* env = AndroidRuntime::getJNIEnv();

    ScopedLocalRef<jobject> receiverObj(env, jniGetReferent(env, mReceiverWeakGlobal));
    if (receiverObj.get()) {
        ALOGV("receiver %p ~ Invoking vsync handler.", this);
        env->CallVoidMethod(receiverObj.get(),
                gDisplayEventReceiverClassInfo.dispatchVsync, timestamp, id, count);
        ALOGV("receiver %p ~ Returned from vsync handler.", this);
    }

    mMessageQueue->raiseAndClearException(env, "dispatchVsync");
}

这里是利用jni反调了DisplayEventReceiver.java类的dispatchVsync函数。

(3)、DisplayEventReceiver.dispatchVsync()(Java层回调)

我们再来看看DisplayEventReceiver java类的dispatchVsync函数,调用了onVsync函数。

G:\android9.0\frameworks\base\core\java\android\view\DisplayEventReceiver.java

private void dispatchVsync(long timestampNanos, int builtInDisplayId, int frame) {
    onVsync(timestampNanos, builtInDisplayId, frame);
}

而这个onVsync是一个空函数,具体在其子类中实现了。

G:\android9.0\frameworks\base\core\java\android\view\Choreographer.java
    private final class FrameDisplayEventReceiver extends DisplayEventReceiver
            implements Runnable {
        private boolean mHavePendingVsync;
        private long mTimestampNanos;
        private int mFrame;

        public FrameDisplayEventReceiver(Looper looper, int vsyncSource) {
            super(looper, vsyncSource);
        }

        @Override
        public void onVsync(long timestampNanos, int builtInDisplayId, int frame) {
            ......
            if (builtInDisplayId != SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN) {
                ......
                scheduleVsync();
                return;
            }

            ......
            long now = System.nanoTime();
            if (timestampNanos > now) {
                ......
                timestampNanos = now;
            }

            if (mHavePendingVsync) {
               ......
            } else {
                mHavePendingVsync = true;
            }

            mTimestampNanos = timestampNanos;
            mFrame = frame;
            Message msg = Message.obtain(mHandler, this);
            msg.setAsynchronous(true);
            mHandler.sendMessageAtTime(msg, timestampNanos / TimeUtils.NANOS_PER_MS);
        }

        @Override
        public void run() {
            mHavePendingVsync = false;
            doFrame(mTimestampNanos, mFrame);
        }
    }

Message msg = Message.obtain(mHandler, this)最终会调用run()。

(4)、 doFrame(mTimestampNanos, mFrame)
G:\android9.0\frameworks\base\core\java\android\view\Choreographer.java

    void doFrame(long frameTimeNanos, int frame) {
        final long startNanos;
        synchronized (mLock) {

            long intendedFrameTimeNanos = frameTimeNanos;
            startNanos = System.nanoTime();
            final long jitterNanos = startNanos - frameTimeNanos;
            if (jitterNanos >= mFrameIntervalNanos) {
                final long skippedFrames = jitterNanos / mFrameIntervalNanos;
                ......
                final long lastFrameOffset = jitterNanos % mFrameIntervalNanos;
                ......
                frameTimeNanos = startNanos - lastFrameOffset;
            }

            if (frameTimeNanos < mLastFrameTimeNanos) {
                ......
                scheduleVsyncLocked();
                return;
            }

            if (mFPSDivisor > 1) {
                long timeSinceVsync = frameTimeNanos - mLastFrameTimeNanos;
                if (timeSinceVsync < (mFrameIntervalNanos * mFPSDivisor) && timeSinceVsync > 0) {
                    scheduleVsyncLocked();
                    return;
                }
            }

            mFrameInfo.setVsync(intendedFrameTimeNanos, frameTimeNanos);
            mFrameScheduled = false;
            mLastFrameTimeNanos = frameTimeNanos;
        }

        try {
            Trace.traceBegin(Trace.TRACE_TAG_VIEW, "Choreographer#doFrame");
            AnimationUtils.lockAnimationClock(frameTimeNanos / TimeUtils.NANOS_PER_MS);

            mFrameInfo.markInputHandlingStart();
            doCallbacks(Choreographer.CALLBACK_INPUT, frameTimeNanos);

            mFrameInfo.markAnimationsStart();
            doCallbacks(Choreographer.CALLBACK_ANIMATION, frameTimeNanos);

            mFrameInfo.markPerformTraversalsStart();
            doCallbacks(Choreographer.CALLBACK_TRAVERSAL, frameTimeNanos);

            doCallbacks(Choreographer.CALLBACK_COMMIT, frameTimeNanos);
        } finally {
            AnimationUtils.unlockAnimationClock();
            Trace.traceEnd(Trace.TRACE_TAG_VIEW);
        }
       .....
    }

Choreographer类中分别定义了CallbackRecord、CallbackQueue内部类,CallbackQueue是一个按时间先后顺序保存CallbackRecord的单向循环链表。

在Choreographer中定义了三个CallbackQueue队列,用数组mCallbackQueues表示,用于分别保存CALLBACK_INPUT、CALLBACK_ANIMATION、CALLBACK_TRAVERSAL这三种类型的Callback,当调用Choreographer类的postCallback()函数时,就是往指定类型的CallbackQueue队列中通过addCallbackLocked()函数添加一个CallbackRecord项:首先构造一个CallbackRecord对象,然后按时间先后顺序插入到CallbackQueue链表中。从代码注释中,我们可以知道CALLBACK_INPUT是指输入回调,该回调优先级最高,首先得到执行,而CALLBACK_TRAVERSAL是指处理布局和绘图的回调,只有在所有异步消息都执行完后才得到执行,CALLBACK_ANIMATION是指动画回调,比CALLBACK_TRAVERSAL优先执行,从doFrame()函数中的doCallbacks调用就能印证这点。 当Vsync事件到来时,顺序执行CALLBACK_INPUT、CALLBACK_ANIMATION、CALLBACK_TRAVERSAL 和CALLBACK_COMMIT 对应CallbackQueue队列中注册的回调。

关于Choreographer的postCallback()用法在前面进行了详细的介绍,当Vsync事件到来时,mTraversalRunnable对象的run()函数将被调用。

mTraversalRunnable对象的类型为TraversalRunnable,该类实现了Runnable接口,在其run()函数中调用了doTraversal()函数来完成窗口布局。

G:\android9.0\frameworks\base\core\java\android\view\ViewRootImpl.java

final class TraversalRunnable implements Runnable {
    @Override
    public void run() {
        doTraversal();
    }
}
(5)、 ViewRootImpl.doTraversal()
G:\android9.0\frameworks\base\core\java\android\view\ViewRootImpl.java

    void doTraversal() {
        if (mTraversalScheduled) {
            mTraversalScheduled = false;
            mHandler.getLooper().getQueue().removeSyncBarrier(mTraversalBarrier);

            if (mProfile) {
                Debug.startMethodTracing("ViewAncestor");
            }

            performTraversals();

            if (mProfile) {
                Debug.stopMethodTracing();
                mProfile = false;
            }
        }
    }

(三)、Vsync 信号处理

performTraversals函数相当复杂,其主要实现以下几个重要步骤:

  • 1.执行窗口测量;

  • 2.执行窗口注册;

  • 3.执行窗口布局;

  • 4.执行窗口绘图;

G:\android9.0\frameworks\base\core\java\android\view\ViewRootImpl.java

    private void performTraversals() {
        // cache mView since it is used so much below...
        final View host = mView;


----------------------------------------------------------------
对应Log:
04-16 13:08:36.978 I/System.out( 2602): ======================================
04-16 13:08:36.978 I/System.out( 2602): performTraversals
04-16 13:08:36.978 D/View    ( 2602):   + DecorView@515e1ca[TestActivity]
04-16 13:08:36.978 D/View    ( 2602):       frame={0, 0, 0, 0} scroll={0, 0} 
04-16 13:08:36.978 D/View    ( 2602):       mMeasureWidth=0 mMeasureHeight=0
view.java  ===>>> output = mLayoutParams.debug(output);

04-16 13:08:36.991 D/Debug   ( 2602):       Contents of {(0,0)(fillxfill) sim={forwardNavigation} ty=BASE_APPLICATION fmt=TRANSPARENT wanim=0x1030000
04-16 13:08:36.991 D/Debug   ( 2602):   fl=LAYOUT_IN_SCREEN LAYOUT_INSET_DECOR SPLIT_TOUCH HARDWARE_ACCELERATED}:
04-16 13:08:36.991 D/Debug   ( 2602): ViewGroup.LayoutParams={ width=match-parent, height=match-parent }
04-16 13:08:36.991 D/Debug   ( 2602): 
04-16 13:08:36.991 D/Debug   ( 2602): WindowManager.LayoutParams={title=com.android.testred/com.android.testred.TestActivity}
----------------------------------------------------------------
        if (DBG) {
            System.out.println("======================================");
            System.out.println("performTraversals");
            host.debug();
        }

        if (host == null || !mAdded)
            return;

        mIsInTraversal = true;
        mWillDrawSoon = true;
        boolean windowSizeMayChange = false;
        boolean newSurface = false;
        boolean surfaceChanged = false;
        WindowManager.LayoutParams lp = mWindowAttributes;

        int desiredWindowWidth;
        int desiredWindowHeight;

        final int viewVisibility = getHostVisibility();
        ......
        final boolean viewUserVisibilityChanged = !mFirst &&
                ((mViewVisibility == View.VISIBLE) != (viewVisibility == View.VISIBLE));

        WindowManager.LayoutParams params = null;
        if (mWindowAttributesChanged) {
            mWindowAttributesChanged = false;
            surfaceChanged = true;
            params = lp;
        }
        CompatibilityInfo compatibilityInfo =
                mDisplay.getDisplayAdjustments().getCompatibilityInfo();
        if (compatibilityInfo.supportsScreen() == mLastInCompatMode) {
            params = lp;
            mFullRedrawNeeded = true;
            mLayoutRequested = true;
            if (mLastInCompatMode) {
                params.privateFlags &= ~WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
                mLastInCompatMode = false;
            } else {
                params.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
                mLastInCompatMode = true;
            }
        }

        mWindowAttributesChangesFlag = 0;

        Rect frame = mWinFrame;
        if (mFirst) {
            mFullRedrawNeeded = true;
            mLayoutRequested = true;

            final Configuration config = mContext.getResources().getConfiguration();
            if (shouldUseDisplaySize(lp)) {
                // NOTE -- system code, won't try to do compat mode.
                Point size = new Point();
                mDisplay.getRealSize(size);
                desiredWindowWidth = size.x;
                desiredWindowHeight = size.y;
            } else {
                desiredWindowWidth = mWinFrame.width();
                desiredWindowHeight = mWinFrame.height();
            }

            ......
            // Set the layout direction if it has not been set before (inherit is the default)
            if (mViewLayoutDirectionInitial == View.LAYOUT_DIRECTION_INHERIT) {
                host.setLayoutDirection(config.getLayoutDirection());
            }
            host.dispatchAttachedToWindow(mAttachInfo, 0);
            mAttachInfo.mTreeObserver.dispatchOnWindowAttachedChange(true);
            dispatchApplyInsets(host);
        } else {
            desiredWindowWidth = frame.width();
            desiredWindowHeight = frame.height();
            ......
        }

       ......
        boolean insetsChanged = false;

        boolean layoutRequested = mLayoutRequested && (!mStopped || mReportNextDraw);
        if (layoutRequested) {

            final Resources res = mView.getContext().getResources();

            if (mFirst) {
                // make sure touch mode code executes by setting cached value
                // to opposite of the added touch mode.
                mAttachInfo.mInTouchMode = !mAddedTouchMode;
                ensureTouchModeLocally(mAddedTouchMode);
            } else {
                ......
                if (!mPendingVisibleInsets.equals(mAttachInfo.mVisibleInsets)) {
                    mAttachInfo.mVisibleInsets.set(mPendingVisibleInsets);
                    if (DEBUG_LAYOUT) Log.v(mTag, "Visible insets changing to: "
                            + mAttachInfo.mVisibleInsets);
                }
                ......
                if (lp.width == ViewGroup.LayoutParams.WRAP_CONTENT
                        || lp.height == ViewGroup.LayoutParams.WRAP_CONTENT) {
                    windowSizeMayChange = true;

                    if (shouldUseDisplaySize(lp)) {
                        // NOTE -- system code, won't try to do compat mode.
                        Point size = new Point();
                        mDisplay.getRealSize(size);
                        desiredWindowWidth = size.x;
                        desiredWindowHeight = size.y;
                    } else {
                        Configuration config = res.getConfiguration();
                        desiredWindowWidth = dipToPx(config.screenWidthDp);
                        desiredWindowHeight = dipToPx(config.screenHeightDp);
                    }
                }
            }

            // Ask host how big it wants to be
            windowSizeMayChange |= measureHierarchy(host, lp, res,
                    desiredWindowWidth, desiredWindowHeight);
        }

        if (collectViewAttributes()) {
            params = lp;
        }
        if (mAttachInfo.mForceReportNewAttributes) {
            mAttachInfo.mForceReportNewAttributes = false;
            params = lp;
        }
        ......

/****************执行窗口测量******************/  
        if (mApplyInsetsRequested) {
            mApplyInsetsRequested = false;
            mLastOverscanRequested = mAttachInfo.mOverscanRequested;
            dispatchApplyInsets(host);
            if (mLayoutRequested) {
                // Short-circuit catching a new layout request here, so
                // we don't need to go through two layout passes when things
                // change due to fitting system windows, which can happen a lot.
----------------------------------------------------------------
对应Log:
04-16 13:08:36.985 V/ViewRootImpl[TestActivity]( 2602): Measuring DecorView@515e1ca[TestActivity] in display 480x782...
04-16 13:08:36.988 I/System.out( 2602): ======================================
04-16 13:08:36.988 I/System.out( 2602): performTraversals -- after measure
----------------------------------------------------------------
                windowSizeMayChange |= measureHierarchy(host, lp,
                        mView.getContext().getResources(),
                        desiredWindowWidth, desiredWindowHeight);
            }
        }

        if (layoutRequested) {
            // Clear this now, so that if anything requests a layout in the
            // rest of this function we will catch it and re-run a full
            // layout pass.
            mLayoutRequested = false;
        }

        boolean windowShouldResize ...;
        windowShouldResize |= mDragResizing && mResizeMode == RESIZE_MODE_FREEFORM;

        windowShouldResize |= mActivityRelaunched;

        final boolean computesInternalInsets ...;

        boolean insetsPending = false;
        int relayoutResult = 0;
        boolean updatedConfiguration = false;

        final int surfaceGenerationId = mSurface.getGenerationId();

        final boolean isViewVisible = viewVisibility == View.VISIBLE;
        final boolean windowRelayoutWasForced = mForceNextWindowRelayout;
        if (mFirst || windowShouldResize || insetsChanged ||
                viewVisibilityChanged || params != null || mForceNextWindowRelayout) {
            mForceNextWindowRelayout = false;

            if (isViewVisible) {
                insetsPending = computesInternalInsets && (mFirst || viewVisibilityChanged);
            }

            if (mSurfaceHolder != null) {
                mSurfaceHolder.mSurfaceLock.lock();
                mDrawingAllowed = true;
            }

            boolean hwInitialized = false;
            boolean contentInsetsChanged = false;
            boolean hadSurface = mSurface.isValid();

            try {
----------------------------------------------------------------
对应Log:
04-16 13:08:36.995 I/ViewRootImpl[TestActivity]( 2602): host=w:480, h:782, params={(0,0)(fillxfill) sim={adjust=pan forwardNavigation} ty=BASE_APPLICATION fmt=TRANSPARENT wanim=0x1030000
04-16 13:08:36.995 I/ViewRootImpl[TestActivity]( 2602):   fl=LAYOUT_IN_SCREEN LAYOUT_INSET_DECOR SPLIT_TOUCH HARDWARE_ACCELERATED}
----------------------------------------------------------------
                if (DEBUG_LAYOUT) {
                    Log.i(mTag, "host=w:" + host.getMeasuredWidth() + ", h:" +
                            host.getMeasuredHeight() + ", params=" + params);
                }

                if (mAttachInfo.mThreadedRenderer != null) {
                    if (mAttachInfo.mThreadedRenderer.pauseSurface(mSurface)) {
                        mDirty.set(0, 0, mWidth, mHeight);
                    }
                    mChoreographer.mFrameInfo.addFlags(FrameInfo.FLAG_WINDOW_LAYOUT_CHANGED);
                }

 /****************请求WMS服务relayout窗口******************/  
----------------------------------------------------------------
对应Log:
04-16 13:08:36.997 D/ViewRootImpl[TestActivity]( 2602): WindowLayout in layoutWindow:{(0,0)(fillxfill) sim={adjust=pan forwardNavigation} ty=BASE_APPLICATION fmt=TRANSPARENT wanim=0x1030000
04-16 13:08:36.997 D/ViewRootImpl[TestActivity]( 2602):   fl=LAYOUT_IN_SCREEN LAYOUT_INSET_DECOR SPLIT_TOUCH HARDWARE_ACCELERATED}
----------------------------------------------------------------

                relayoutResult = relayoutWindow(params, viewVisibility, insetsPending);
(1)、请求WMS服务relayout窗口mWindowSession.relayout()
G:\android9.0\frameworks\base\core\java\android\view\ViewRootImpl.java

   private int relayoutWindow(WindowManager.LayoutParams params, int viewVisibility,
            boolean insetsPending) throws RemoteException {

        float appScale = mAttachInfo.mApplicationScale;
        boolean restore = false;
        if (params != null && mTranslator != null) {
            restore = true;
            params.backup();
            mTranslator.translateWindowLayout(params);
        }

        if (params != null) {
            if (DBG) Log.d(mTag, "WindowLayout in layoutWindow:" + params);

            if (mOrigWindowType != params.type) {
                // For compatibility with old apps, don't crash here.
                if (mTargetSdkVersion < Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
                    Slog.w(mTag, "Window type can not be changed after "
                            + "the window is added; ignoring change of " + mView);
                    params.type = mOrigWindowType;
                }
            }
        }

        long frameNumber = -1;
        if (mSurface.isValid()) {
            frameNumber = mSurface.getNextFrameNumber();
        }

        //zhoujinjian start
        int relayoutResult = 0;
        if(params != null ){
                        if("com.android.testred".equals(params.packageName) 
                || "com.android.testgreen".equals(params.packageName)
                || "com.android.testblue".equals(params.packageName)){
                Point size = new Point();
                mDisplay.getRealSize(size);
                params.width = (int) size.x / 3;
                params.height = (int) size.y;

                relayoutResult = mWindowSession.relayout(mWindow, mSeq, params,
                (int) size.x / 3,
                (int) size.y, viewVisibility,
                insetsPending ? WindowManagerGlobal.RELAYOUT_INSETS_PENDING : 0, frameNumber,
                mWinFrame, mPendingOverscanInsets, mPendingContentInsets, mPendingVisibleInsets,
                mPendingStableInsets, mPendingOutsets, mPendingBackDropFrame, mPendingDisplayCutout,
                mPendingMergedConfiguration, mSurface);

            }else {
                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,
                mWinFrame, mPendingOverscanInsets, mPendingContentInsets, mPendingVisibleInsets,
                mPendingStableInsets, mPendingOutsets, mPendingBackDropFrame, mPendingDisplayCutout,
                mPendingMergedConfiguration, mSurface);
            }
        }
        //zhoujinjian end
        mPendingAlwaysConsumeNavBar =
                (relayoutResult & WindowManagerGlobal.RELAYOUT_RES_CONSUME_ALWAYS_NAV_BAR) != 0;

        if (restore) {
            params.restore();
        }

        if (mTranslator != null) {
            mTranslator.translateRectInScreenToAppWinFrame(mWinFrame);
            mTranslator.translateRectInScreenToAppWindow(mPendingOverscanInsets);
            mTranslator.translateRectInScreenToAppWindow(mPendingContentInsets);
            mTranslator.translateRectInScreenToAppWindow(mPendingVisibleInsets);
            mTranslator.translateRectInScreenToAppWindow(mPendingStableInsets);
        }
        return relayoutResult;
    }

这里通过前面获取的IWindowSession代理对象请求WMS服务执行窗口布局,mSurface是ViewRootImpl的成员变量 [->ViewRootImpl.java]

该Surface构造函数仅仅创建了一个空Surface对象,并没有对该Surface进程native层的初始化,到此我们知道应用程序进程为每个窗口对象都创建了一个Surface对象。并且将该Surface通过跨进程方式传输给WMS服务进程,我们知道,在Android系统中,如果一个对象需要在不同进程间传输,必须实现Parcelable接口,Surface类正好实现了Parcelable接口。ViewRootImpl通过IWindowSession接口请求WMS的完整过程如下:

Android 9.0已改变没有直接提供Java源码,而是.class文件打包为classes-header.jar和classes.jar。
android\out\target\common\obj\JAVA_LIBRARIES\framework_intermediates\
classes-header.jar
classes.jar解压:
classes/android/view/
    IWindowSession.class
    IWindowSession$Stub.class
    IWindowSession$Stub$Proxy.class

[解压后在线反编译](http://www.javadecompilers.com/)
or
[解压后在线反编译](http://javare.cn/)
-----------------------------------------------------------------------------------------------
IWindowSession.java
public interface IWindowSession extends IInterface {
  ......
   int addToDisplay(IWindow var1, int var2, LayoutParams var3, int var4, int var5, Rect var6, Rect var7, Rect var8, Rect var9, ParcelableWrapper var10, InputChannel var11) throws RemoteException;

   ......

   int relayout(IWindow var1, int var2, LayoutParams var3, int var4, int var5, int var6, int var7, long var8, Rect var10, Rect var11, Rect var12, Rect var13, Rect var14, Rect var15, Rect var16, ParcelableWrapper var17, MergedConfiguration var18, Surface var19) throws RemoteException;

   ......
}

-----------------------------------------------------------------------------------------------
IWindowSession$Stub.java

public abstract class IWindowSession$Stub extends Binder implements IWindowSession {

   private static final String DESCRIPTOR = "android.view.IWindowSession";
   static final int TRANSACTION_addToDisplay = 2;
   static final int TRANSACTION_relayout = 6;
   public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
      String descriptor = "android.view.IWindowSession";
      IWindow _arg0;
      ......
      switch(code) {
      case 2:
         data.enforceInterface(descriptor);
         _arg0 = Stub.asInterface(data.readStrongBinder());
         _arg1 = data.readInt();
         if(0 != data.readInt()) {
            _arg25 = (LayoutParams)LayoutParams.CREATOR.createFromParcel(data);
         } else {
            _arg25 = null;
         }

         _arg3 = data.readInt();
         _arg4 = data.readInt();
         _arg53 = new Rect();
         _arg63 = new Rect();
         Rect _result6 = new Rect();
         Rect _arg81 = new Rect();
         ParcelableWrapper _result8 = new ParcelableWrapper();
         InputChannel _arg91 = new InputChannel();
         int _arg101 = this.addToDisplay(_arg0, _arg1, _arg25, _arg3, _arg4, _arg53, _arg63, _result6, _arg81, _result8, _arg91);
         ......

         return true;
     case 6:
         data.enforceInterface(descriptor);
         _arg0 = Stub.asInterface(data.readStrongBinder());
         _arg1 = data.readInt();
         if(0 != data.readInt()) {
            _arg25 = (LayoutParams)LayoutParams.CREATOR.createFromParcel(data);
         } else {
            _arg25 = null;
         }

        ......
         ParcelableWrapper _arg15 = new ParcelableWrapper();
         MergedConfiguration _arg16 = new MergedConfiguration();
         Surface _arg17 = new Surface();
         int _result2 = this.relayout(_arg0, _arg1, _arg25, _arg3, _arg4, _arg5, _arg62, _result4, _result7, _arg9, _arg10, _arg11, _arg12, _arg13, _arg14, _arg15, _arg16, _arg17);
         ......
         if(_arg17 != null) {
            reply.writeInt(1);
            _arg17.writeToParcel(reply, 1);
         } else {
            reply.writeInt(0);
         }
         return true;
}

从该函数的实现可以看出,应用程序进程中创建的Surface对象并没有传递到WMS服务进程,只是读取WMS服务进程返回来的Surface。那么WMS服务进程是如何响应应用程序进程布局请求的呢?

-----------------------------------------------------------------------------------------------
IWindowSession$Stub$Proxy.java

class IWindowSession$Stub$Proxy
  implements IWindowSession
{
  private IBinder mRemote;

  IWindowSession$Stub$Proxy(IBinder remote)
  {
    mRemote = remote;
  }

  public IBinder asBinder() {
    return mRemote;
  }

  public String getInterfaceDescriptor() {
    return "android.view.IWindowSession";
  }
  public int addToDisplay(IWindow window, int seq, WindowManager.LayoutParams attrs, int viewVisibility, int layerStackId, Rect outFrame, Rect outContentInsets, Rect outStableInsets, Rect outOutsets, DisplayCutout.ParcelableWrapper displayCutout, InputChannel outInputChannel) throws RemoteException {
    Parcel _data = Parcel.obtain();
    Parcel _reply = Parcel.obtain();
    try
    {
      _data.writeInterfaceToken("android.view.IWindowSession");
      _data.writeStrongBinder(window != null ? window.asBinder() : null);
      _data.writeInt(seq);
      if (attrs != null) {
        _data.writeInt(1);
        attrs.writeToParcel(_data, 0);
      }
      else {
        _data.writeInt(0);
      }
      _data.writeInt(viewVisibility);
      _data.writeInt(layerStackId);
      mRemote.transact(2, _data, _reply, 0);
      _reply.readException();
      int _result = _reply.readInt();
      ......
    }
    finally {
      _reply.recycle();
      _data.recycle(); }
    int _result;
    return _result;
  }

  public int relayout(IWindow window, int seq, WindowManager.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 displayCutout, MergedConfiguration outMergedConfiguration, Surface outSurface) throws RemoteException {
    Parcel _data = Parcel.obtain();
    Parcel _reply = Parcel.obtain();
    try
    {
      _data.writeInterfaceToken("android.view.IWindowSession");
      _data.writeStrongBinder(window != null ? window.asBinder() : null);
      _data.writeInt(seq);
      if (attrs != null) {
        _data.writeInt(1);
        attrs.writeToParcel(_data, 0);
      }
      else {
        _data.writeInt(0);
      }
      _data.writeInt(requestedWidth);
      _data.writeInt(requestedHeight);
      _data.writeInt(viewVisibility);
      _data.writeInt(flags);
      _data.writeLong(frameNumber);
      mRemote.transact(6, _data, _reply, 0);
      _reply.readException();
      int _result = _reply.readInt();
      ......
      if (0 != _reply.readInt()) {
        outSurface.readFromParcel(_reply);
      }
    }
    finally {
      _reply.recycle();
      _data.recycle(); }
    int _result;
    return _result;
  }

}
-----------------------------------------------------------------------------------------------

该函数可以看出,WMS服务在响应应用程序进程请求添加窗口时,首先在当前进程空间创建一个Surface对象,然后调用Session的relayout()函数进一步完成窗口添加过程,最后将WMS服务中创建的Surface返回给应用程序进程。

1.1、Session.relayout()
G:\android9.0\frameworks\base\services\core\java\com\android\server\wm\Session.java

    @Override
    public int relayout(IWindow window, int seq, WindowManager.LayoutParams attrs,
            int requestedWidth, int requestedHeight, int viewFlags, int flags, long frameNumber,
            Rect outFrame, Rect outOverscanInsets, Rect outContentInsets, Rect outVisibleInsets,
            Rect outStableInsets, Rect outsets, Rect outBackdropFrame,
            DisplayCutout.ParcelableWrapper cutout, MergedConfiguration mergedConfiguration,
            Surface outSurface) {
        if (false) Slog.d(TAG_WM, ">>>>>> ENTERED relayout from "
                + Binder.getCallingPid());
        Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, mRelayoutTag);
        int res = mService.relayoutWindow(this, window, seq, attrs,
                requestedWidth, requestedHeight, viewFlags, flags, frameNumber,
                outFrame, outOverscanInsets, outContentInsets, outVisibleInsets,
                outStableInsets, outsets, outBackdropFrame, cutout,
                mergedConfiguration, outSurface);
        Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
        if (false) Slog.d(TAG_WM, "<<<<<< EXITING relayout to "
                + Binder.getCallingPid());
        return res;
    }
1.2、WindowManagerService.relayoutWindow()
G:\android9.0\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,
            Surface outSurface) {
        int result = 0;
        boolean configChanged;
        ......
        long origId = Binder.clearCallingIdentity();
        final int displayId;
        synchronized(mWindowMap) {
----------------------------------------------------------------
对应Log:
04-16 13:08:36.998 V/WindowManager( 1049): Looking up client android.os.BinderProxy@b9baf64: Window{c1255cd u0 com.android.testred/com.android.testred.TestActivity}
    final WindowState windowForClientLocked(Session session, IBinder client, boolean throwOnError) {
        WindowState win = mWindowMap.get(client);
        if (localLOGV) Slog.v(TAG_WM, "Looking up client " + client + ": " + win);
        return win;
    }
----------------------------------------------------------------
            WindowState win = windowForClientLocked(session, client, false);

            displayId = win.getDisplayId();
            //得到WindowStateAnimator
            WindowStateAnimator winAnimator = win.mWinAnimator;
            ......
            win.setFrameNumber(frameNumber);
            int attrChanges = 0;
            int flagChanges = 0;
            if (attrs != null) {
                mPolicy.adjustWindowParamsLw(win, attrs, hasStatusBarServicePermission);
                ......
            }
----------------------------------------------------------------
对应Log:
04-16 13:08:37.000 V/WindowManager( 1049): Relayout Window{c1255cd u0 com.android.testred/com.android.testred.TestActivity}: viewVisibility=0 req=160x854 {(0,0)(160x854) sim={adjust=pan forwardNavigation} ty=BASE_APPLICATION fmt=TRANSPARENT wanim=0x1030000
04-16 13:08:37.000 V/WindowManager( 1049):   fl=LAYOUT_IN_SCREEN LAYOUT_INSET_DECOR SPLIT_TOUCH HARDWARE_ACCELERATED}

----------------------------------------------------------------

            if (DEBUG_LAYOUT) Slog.v(TAG_WM, "Relayout " + win + ": viewVisibility=" + viewVisibility
                    + " req=" + requestedWidth + "x" + requestedHeight + " " + win.mAttrs);
            ......
            win.setWindowScale(win.mRequestedWidth, win.mRequestedHeight);

            ......

            final int oldVisibility = win.mViewVisibility;

            .......
            win.mViewVisibility = viewVisibility;
            if (DEBUG_SCREEN_ON) {
----------------------------------------------------------------
对应Log:
04-16 13:08:37.001 I/WindowManager( 1049): Relayout Window{c1255cd u0 com.android.testred/com.android.testred.TestActivity}: oldVis=4 newVis=0
04-16 13:08:37.001 I/WindowManager( 1049): java.lang.RuntimeException
04-16 13:08:37.001 I/WindowManager( 1049):     at com.android.server.wm.WindowManagerService.relayoutWindow(WindowManagerService.java:1994)
04-16 13:08:37.001 I/WindowManager( 1049):     at com.android.server.wm.Session.relayout(Session.java:244)
04-16 13:08:37.001 I/WindowManager( 1049):     at android.view.IWindowSession$Stub.onTransact(IWindowSession.java:309)
04-16 13:08:37.001 I/WindowManager( 1049):     at com.android.server.wm.Session.onTransact(Session.java:164)
04-16 13:08:37.001 I/WindowManager( 1049):     at android.os.Binder.execTransact(Binder.java:731)

----------------------------------------------------------------
                RuntimeException stack = new RuntimeException();
                stack.fillInStackTrace();
                Slog.i(TAG_WM, "Relayout " + win + ": oldVis=" + oldVisibility
                        + " newVis=" + viewVisibility, stack);
            }

----------------------------------------------------------------
对应Log:
04-16 13:08:37.001 W/WindowManager( 1049): setLayoutNeeded: callers=com.android.server.wm.WindowState.setDisplayLayoutNeeded:2250 com.android.server.wm.WindowManagerService.relayoutWindow:1999 com.android.server.wm.Session.relayout:244 


G:\android9.0\frameworks\base\services\core\java\com\android\server\wm\WindowState.java
    void setLayoutNeeded() {
        if (DEBUG_LAYOUT) Slog.w(TAG_WM, "setLayoutNeeded: callers=" + Debug.getCallers(3));
        mLayoutNeeded = true;
    }
----------------------------------------------------------------



            win.setDisplayLayoutNeeded();
            win.mGivenInsetsPending = (flags & WindowManagerGlobal.RELAYOUT_INSETS_PENDING) != 0;

            ......
            // We may be deferring layout passes at the moment, but since the client is interested
            // in the new out values right now we need to force a layout.
            mWindowPlacerLocked.performSurfacePlacement(true /* force */);

            if (shouldRelayout) {

                result = win.relayoutVisibleWindow(result, attrChanges, oldVisibility);

                try {
                    result = createSurfaceControl(outSurface, result, win, winAnimator);
                } catch (Exception e) {
                    ......
                    return 0;
                }
            } else {
                Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "relayoutWindow: viewVisibility_2");

                winAnimator.mEnterAnimationPending = false;
                winAnimator.mEnteringAnimation = false;

                if (viewVisibility == View.VISIBLE && winAnimator.hasSurface()) {
                    winAnimator.mSurfaceController.getSurface(outSurface);
                } else {
                    if (DEBUG_VISIBILITY) Slog.i(TAG_WM, "Releasing surface in: " + win);
                    try {
                        outSurface.release();
                    } finally {
                        Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
                    }
                }

                Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
            }

            if (focusMayChange) {
                //System.out.println("Focus may change: " + win.mAttrs.getTitle());
                //更新Focus窗口
                if (updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
                        false /*updateInputWindows*/)) {
                    imMayMove = false;
                }
            }

            // updateFocusedWindowLocked() already assigned layers so we only need to
            // reassign them at this point if the IM window state gets shuffled
            boolean toBeDisplayed = (result & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0;
            final DisplayContent dc = win.getDisplayContent();
            if (imMayMove) {
                dc.computeImeTarget(true /* updateImeTarget */);
                if (toBeDisplayed) {
                    dc.assignWindowLayers(false /* setLayoutNeeded */);
                }
            }

           .......
----------------------------------------------------------------
对应Log:
Line 3541: 04-16 13:08:37.071 V/WindowManager( 1049): Relayout given client android.os.BinderProxy@b9baf64, requestedWidth=160, requestedHeight=854, viewVisibility=0
Line 3542: 04-16 13:08:37.071 V/WindowManager( 1049): Relayout returning frame=Rect(0, 0 - 160, 854), surface=Surface(name=null)/@0xc820bda
Line 3543: 04-16 13:08:37.071 V/WindowManager( 1049): Relayout of Window{c1255cd u0 com.android.testred/com.android.testred.TestActivity}: focusMayChange=true
----------------------------------------------------------------
            if (localLOGV) Slog.v(
                TAG_WM, "Relayout given client " + client.asBinder()
                + ", requestedWidth=" + requestedWidth
                + ", requestedHeight=" + requestedHeight
                + ", viewVisibility=" + viewVisibility
                + "\nRelayout returning frame=" + outFrame
                + ", surface=" + outSurface);

            if (localLOGV || DEBUG_FOCUS) Slog.v(
                TAG_WM, "Relayout of " + win + ": focusMayChange=" + focusMayChange);

            result |= mInTouchMode ? WindowManagerGlobal.RELAYOUT_RES_IN_TOUCH_MODE : 0;

            mInputMonitor.updateInputWindowsLw(true /*force*/);

            if (DEBUG_LAYOUT) {
                Slog.v(TAG_WM, "Relayout complete " + win + ": outFrame=" + outFrame.toShortString());
            }
            win.mInRelayout = false;
        }
        ......
        return result;
    }
1.2.1、WindowSurfacePlacer.performSurfacePlaRelayout complete cement(true /* force */)

首先看下堆栈信息:


04-16 13:08:37.001 V/RootWindowContainer( 1049): performSurfacePlacementInner: entry. Called by com.android.server.wm.WindowSurfacePlacer.performSurfacePlacementLoop:207 com.android.server.wm.WindowSurfacePlacer.performSurfacePlacement:155 com.android.server.wm.WindowManagerService.relayoutWindow:2031 
G:\android9.0\frameworks\base\services\core\java\com\android\server\wm\WindowSurfacePlacer.java

    final void performSurfacePlacement(boolean force) {
        if (mDeferDepth > 0 && !force) {
            return;
        }
        int loopCount = 6;
        do {
            mTraversalScheduled = false;
            performSurfacePlacementLoop();
            mService.mAnimationHandler.removeCallbacks(mPerformSurfacePlacement);
            loopCount--;
        } while (mTraversalScheduled && loopCount > 0);
        mService.mRoot.mWallpaperActionPending = false;
    }


    private void performSurfacePlacementLoop() {
        ......
        mInLayout = true;

        boolean recoveringMemory = false;
        ......

        try {
            mService.mRoot.performSurfacePlacement(recoveringMemory);

            mInLayout = false;

            if (mService.mRoot.isLayoutNeeded()) {
                if (++mLayoutRepeatCount < 6) {
                    requestTraversal();
                } else {
                    Slog.e(TAG, "Performed 6 layouts in a row. Skipping");
                    mLayoutRepeatCount = 0;
                }
            } else {
                mLayoutRepeatCount = 0;
            }

            if (mService.mWindowsChanged && !mService.mWindowChangeListeners.isEmpty()) {
                mService.mH.removeMessages(REPORT_WINDOWS_CHANGE);
                mService.mH.sendEmptyMessage(REPORT_WINDOWS_CHANGE);
            }
        } catch (RuntimeException e) {
            mInLayout = false;
            Slog.wtf(TAG, "Unhandled exception while laying out windows", e);
        }

    }
1.2.2、RootWindowContainer.performSurfacePlacement(recoveringMemory)
G:\android9.0\frameworks\base\services\core\java\com\android\server\wm\RootWindowContainer.java

    void performSurfacePlacement(boolean recoveringMemory) {
        if (DEBUG_WINDOW_TRACE) Slog.v(TAG, "performSurfacePlacementInner: entry. Called by "
                + Debug.getCallers(3));

        int i;
        boolean updateInputWindowsNeeded = false;

        if (mService.mFocusMayChange) {
            mService.mFocusMayChange = false;
            updateInputWindowsNeeded = mService.updateFocusedWindowLocked(
                    UPDATE_FOCUS_WILL_PLACE_SURFACES, false /*updateInputWindows*/);
        }

        // Initialize state of exiting tokens.
        final int numDisplays = mChildren.size();
        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
            final DisplayContent displayContent = mChildren.get(displayNdx);
            displayContent.setExitingTokensHasVisible(false);
        }

        mHoldScreen = null;
        mScreenBrightness = -1;
        mUserActivityTimeout = -1;
        mObscureApplicationContentOnSecondaryDisplays = false;
        mSustainedPerformanceModeCurrent = false;
        mService.mTransactionSequence++;

        final DisplayContent defaultDisplay = mService.getDefaultDisplayContentLocked();
        final DisplayInfo defaultInfo = defaultDisplay.getDisplayInfo();
        final int defaultDw = defaultInfo.logicalWidth;
        final int defaultDh = defaultInfo.logicalHeight;
----------------------------------------------------------------
对应Log:
04-16 13:08:37.001 I/RootWindowContainer( 1049): >>> OPEN TRANSACTION performLayoutAndPlaceSurfaces
04-16 13:08:37.001 W/WindowManager( 1049): clearLayoutNeeded: callers=com.android.server.wm.DisplayContent.performLayout:2967 com.android.server.wm.DisplayContent.applySurfaceChangesTransaction:2880 com.android.server.wm.RootWindowContainer.applySurfaceChangesTransaction:852 
......
04-16 13:08:37.009 I/RootWindowContainer( 1049): <<< CLOSE TRANSACTION performLayoutAndPlaceSurfaces
----------------------------------------------------------------


        if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
                ">>> OPEN TRANSACTION performLayoutAndPlaceSurfaces");
        mService.openSurfaceTransaction();
        try {
            applySurfaceChangesTransaction(recoveringMemory, defaultDw, defaultDh);
        } catch (RuntimeException e) {
            Slog.wtf(TAG, "Unhandled exception in Window Manager", e);
        } finally {
            mService.closeSurfaceTransaction("performLayoutAndPlaceSurfaces");
            if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
                    "<<< CLOSE TRANSACTION performLayoutAndPlaceSurfaces");
        }

        mService.mAnimator.executeAfterPrepareSurfacesRunnables();

        final WindowSurfacePlacer surfacePlacer = mService.mWindowPlacerLocked;
        // If we are ready to perform an app transition, check through all of the app tokens to be
        // shown and see if they are ready to go.
        if (mService.mAppTransition.isReady()) {
            // This needs to be split into two expressions, as handleAppTransitionReadyLocked may
            // modify dc.pendingLayoutChanges, which would get lost when writing
            // defaultDisplay.pendingLayoutChanges |= handleAppTransitionReadyLocked()
            final int layoutChanges = surfacePlacer.handleAppTransitionReadyLocked();
            defaultDisplay.pendingLayoutChanges |= layoutChanges;
            if (DEBUG_LAYOUT_REPEATS)
                surfacePlacer.debugLayoutRepeats("after handleAppTransitionReadyLocked",
                        defaultDisplay.pendingLayoutChanges);
        }

        ......
        // Check to see if we are now in a state where the screen should
        // be enabled, because the window obscured flags have changed.
        mService.enableScreenIfNeededLocked();

        mService.scheduleAnimationLocked();

        if (DEBUG_WINDOW_TRACE) Slog.e(TAG,
                "performSurfacePlacementInner exit: animating=" + mService.mAnimator.isAnimating());
    }
1.2.2.1、applySurfaceChangesTransaction(recoveringMemory, defaultDw, defaultDh)
G:\android9.0\frameworks\base\services\core\java\com\android\server\wm\RootWindowContainer.java

    private void applySurfaceChangesTransaction(boolean recoveringMemory, int defaultDw,
            int defaultDh) {
        mHoldScreenWindow = null;
        mObscuringWindow = null;

         ......

        boolean focusDisplayed = false;

        final int count = mChildren.size();
        for (int j = 0; j < count; ++j) {
            final DisplayContent dc = mChildren.get(j);
            focusDisplayed |= dc.applySurfaceChangesTransaction(recoveringMemory);
        }

        if (focusDisplayed) {
            mService.mH.sendEmptyMessage(REPORT_LOSING_FOCUS);
        }
        mService.mDisplayManagerInternal.performTraversal(mDisplayTransaction);
        SurfaceControl.mergeToGlobalTransaction(mDisplayTransaction);
    }
1.2.2.2、DisplayContent.applySurfaceChangesTransaction(recoveringMemory)
G:\android9.0\frameworks\base\services\core\java\com\android\server\wm\DisplayContent.java

    boolean applySurfaceChangesTransaction(boolean recoveringMemory) {

        final int dw = mDisplayInfo.logicalWidth;
        final int dh = mDisplayInfo.logicalHeight;
        final WindowSurfacePlacer surfacePlacer = mService.mWindowPlacerLocked;

        mTmpUpdateAllDrawn.clear();

        int repeats = 0;
        do {
            ......

            if ((pendingLayoutChanges & FINISH_LAYOUT_REDO_LAYOUT) != 0) {
                setLayoutNeeded();
            }

            // FIRST LOOP: Perform a layout, if needed.
            if (repeats < LAYOUT_REPEAT_THRESHOLD) {
                performLayout(repeats == 1, false /* updateInputWindows */);
            } else {
                Slog.w(TAG, "Layout repeat skipped after too many iterations");
            }

            // FIRST AND ONE HALF LOOP: Make WindowManagerPolicy think it is animating.
            pendingLayoutChanges = 0;

            if (isDefaultDisplay) {
                mService.mPolicy.beginPostLayoutPolicyLw(dw, dh);
----------------------------------------------------------------
对应Log:

04-16 13:08:37.003 I/WindowManager( 1049): Win Window{c1255cd u0 com.android.testred/com.android.testred.TestActivity}: affectsSystemUi=false
......
----------------------------------------------------------------

                forAllWindows(mApplyPostLayoutPolicy, true /* traverseTopToBottom */);
                pendingLayoutChanges |= mService.mPolicy.finishPostLayoutPolicyLw();
                if (DEBUG_LAYOUT_REPEATS) surfacePlacer.debugLayoutRepeats(
                        "after finishPostLayoutPolicyLw", pendingLayoutChanges);
            }
        } while (pendingLayoutChanges != 0);
        mTmpApplySurfaceChangesTransactionState.reset();
        resetDimming();

        mTmpRecoveringMemory = recoveringMemory;
----------------------------------------------------------------
对应Log:
04-16 13:08:37.007 V/AppWindowToken( 1049): Eval win Window{c1255cd u0 com.android.testred/com.android.testred.TestActivity}: isDrawn=false, isAnimationSet=true
04-16 13:08:37.007 V/AppWindowToken( 1049): Not displayed: s=null pv=true mDrawState=NO_SURFACE ph=false th=false a=true
----------------------------------------------------------------
        forAllWindows(mApplySurfaceChangesTransaction, true /* traverseTopToBottom */);
        ......

        return mTmpApplySurfaceChangesTransactionState.focusDisplayed;
    }
1.2.2.3、DisplayContent.performLayout()
G:\android9.0\frameworks\base\services\core\java\com\android\server\wm\DisplayContent.java

    void performLayout(boolean initial, boolean updateInputWindows) {
        if (!isLayoutNeeded()) {
            return;
        }
        clearLayoutNeeded();

        final int dw = mDisplayInfo.logicalWidth;
        final int dh = mDisplayInfo.logicalHeight;
----------------------------------------------------------------
对应Log:
04-16 13:08:37.001 V/DisplayContent( 1049): -------------------------------------
04-16 13:08:37.001 V/DisplayContent( 1049): performLayout: needed=false dw=480 dh=854
----------------------------------------------------------------
        if (DEBUG_LAYOUT) {
            Slog.v(TAG, "-------------------------------------");
            Slog.v(TAG, "performLayout: needed=" + isLayoutNeeded() + " dw=" + dw + " dh=" + dh);
        }

        mDisplayFrames.onDisplayInfoUpdated(mDisplayInfo,
                calculateDisplayCutoutForRotation(mDisplayInfo.rotation));
        // TODO: Not sure if we really need to set the rotation here since we are updating from the
        // display info above...
        mDisplayFrames.mRotation = mRotation;
        //处理NavigationBar StatusBar窗口布局
        mService.mPolicy.beginLayoutLw(mDisplayFrames, getConfiguration().uiMode);
        if (isDefaultDisplay) {
            // Not needed on non-default displays.
            mService.mSystemDecorLayer = mService.mPolicy.getSystemDecorLayerLw();
            mService.mScreenRect.set(0, 0, dw, dh);
        }

        int seq = mLayoutSeq + 1;
        if (seq < 0) seq = 0;
        mLayoutSeq = seq;

        // Used to indicate that we have processed the dream window and all additional windows are
        // behind it.
        mTmpWindow = null;
        mTmpInitial = initial;

        // First perform layout of any root windows (not attached to another window).
        forAllWindows(mPerformLayout, true /* traverseTopToBottom */);

        // Used to indicate that we have processed the dream window and all additional attached
        // windows are behind it.
        mTmpWindow2 = mTmpWindow;
        mTmpWindow = null;

        // Now perform layout of attached windows, which usually depend on the position of the
        // window they are attached to. XXX does not deal with windows that are attached to windows
        // that are themselves attached.
        forAllWindows(mPerformLayoutAttached, true /* traverseTopToBottom */);

        // Window frames may have changed. Tell the input dispatcher about it.
        mService.mInputMonitor.layoutInputConsumers(dw, dh);
        mService.mInputMonitor.setUpdateInputWindowsNeededLw();
        if (updateInputWindows) {
            mService.mInputMonitor.updateInputWindowsLw(false /*force*/);
        }

        mService.mH.sendEmptyMessage(UPDATE_DOCKED_STACK_DIVIDER);
    }
1.2.2.4、DisplayContent.forAllWindows(mPerformLayout, …)
G:\android9.0\frameworks\base\services\core\java\com\android\server\wm\DisplayContent.java


    private final Consumer<WindowState> mPerformLayout = w -> {
        // Don't do layout of a window if it is not visible, or soon won't be visible, to avoid
        // wasting time and funky changes while a window is animating away.
        final boolean gone = (mTmpWindow != null && mService.mPolicy.canBeHiddenByKeyguardLw(w))
                || w.isGoneForLayoutLw();

----------------------------------------------------------------
对应Log:
......
04-16 13:08:37.002 V/DisplayContent( 1049): 1ST PASS Window{c1255cd u0 com.android.testred/com.android.testred.TestActivity}: gone=false mHaveFrame=false mLayoutAttached=false screen changed=true
04-16 13:08:37.002 V/DisplayContent( 1049):   VIS: mViewVisibility=0 mRelayoutCalled=true hidden=true hiddenRequested=false parentHidden=false
......
----------------------------------------------------------------
        if (DEBUG_LAYOUT && !w.mLayoutAttached) {
            Slog.v(TAG, "1ST PASS " + w + ": gone=" + gone + " mHaveFrame=" + w.mHaveFrame
                    + " mLayoutAttached=" + w.mLayoutAttached
                    + " screen changed=" + w.isConfigChanged());
            final AppWindowToken atoken = w.mAppToken;
            if (gone) Slog.v(TAG, "  GONE: mViewVisibility=" + w.mViewVisibility
                    + " mRelayoutCalled=" + w.mRelayoutCalled + " hidden=" + w.mToken.isHidden()
                    + " hiddenRequested=" + (atoken != null && atoken.hiddenRequested)
                    + " parentHidden=" + w.isParentWindowHidden());
            else Slog.v(TAG, "  VIS: mViewVisibility=" + w.mViewVisibility
                    + " mRelayoutCalled=" + w.mRelayoutCalled + " hidden=" + w.mToken.isHidden()
                    + " hiddenRequested=" + (atoken != null && atoken.hiddenRequested)
                    + " parentHidden=" + w.isParentWindowHidden());
        }

        // If this view is GONE, then skip it -- keep the current frame, and let the caller know
        // so they can ignore it if they want.  (We do the normal layout for INVISIBLE windows,
        // since that means "perform layout as normal, just don't display").
        if (!gone || !w.mHaveFrame || w.mLayoutNeeded
                || ((w.isConfigChanged() || w.setReportResizeHints())
                && !w.isGoneForLayoutLw() &&
                ((w.mAttrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 ||
                        (w.mHasSurface && w.mAppToken != null &&
                                w.mAppToken.layoutConfigChanges)))) {
            if (!w.mLayoutAttached) {
                if (mTmpInitial) {
                    //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial");
                    w.mContentChanged = false;
                }
                if (w.mAttrs.type == TYPE_DREAM) {
                    // Don't layout windows behind a dream, so that if it does stuff like hide
                    // the status bar we won't get a bad transition when it goes away.
                    mTmpWindow = w;
                }
                w.mLayoutNeeded = false;
                w.prelayout();
                final boolean firstLayout = !w.isLaidOut();
                mService.mPolicy.layoutWindowLw(w, null, mDisplayFrames);
                w.mLayoutSeq = mLayoutSeq;

                // If this is the first layout, we need to initialize the last inset values as
                // otherwise we'd immediately cause an unnecessary resize.
                if (firstLayout) {
                    w.updateLastInsetValues();
                }

                if (w.mAppToken != null) {
                    w.mAppToken.layoutLetterbox(w);
                }
----------------------------------------------------------------
对应Log:
04-16 13:08:37.002 V/DisplayContent( 1049):   LAYOUT: mFrame=Rect(0, 0 - 160, 854) mContainingFrame=Rect(0, 0 - 160, 854) mDisplayFrame=Rect(0, 0 - 160, 854)
----------------------------------------------------------------

                if (DEBUG_LAYOUT) Slog.v(TAG, "  LAYOUT: mFrame=" + w.mFrame
                        + " mContainingFrame=" + w.mContainingFrame
                        + " mDisplayFrame=" + w.mDisplayFrame);
            }
        }
    };
1.2.2.5、mService.mPolicy[PhoneWindowManager].layoutWindowLw(w, null, mDisplayFrames)

由之前加入的patch可以知道,我们将App(com.android.testred)的Window宽度强制设置为1/3屏幕宽度,即160。

    @Override
    public void layoutWindowLw(WindowState win, WindowState attached, DisplayFrames displayFrames) {
        // We've already done the navigation bar, status bar, and all screen decor windows. If the
        // status bar can receive input, we need to layout it again to accommodate for the IME
        // window.
        if ((win == mStatusBar && !canReceiveInput(win)) || win == mNavigationBar
                || mScreenDecorWindows.contains(win)) {
            return;
        }
        final WindowManager.LayoutParams attrs = win.getAttrs();
        final boolean isDefaultDisplay = win.isDefaultDisplay();
        final boolean needsToOffsetInputMethodTarget = isDefaultDisplay &&
                (win == mLastInputMethodTargetWindow && mLastInputMethodWindow != null);
        if (needsToOffsetInputMethodTarget) {
            if (DEBUG_LAYOUT) Slog.i(TAG, "Offset ime target window by the last ime window state");
            offsetInputMethodWindowLw(mLastInputMethodWindow, displayFrames);
        }

        final int type = attrs.type;
        final int fl = PolicyControl.getWindowFlags(win, attrs);
        final int pfl = attrs.privateFlags;
        final int sim = attrs.softInputMode;
        final int requestedSysUiFl = PolicyControl.getSystemUiVisibility(null, attrs);
        final int sysUiFl = requestedSysUiFl | getImpliedSysUiFlagsForLayout(attrs);

        final Rect pf = mTmpParentFrame;
        final Rect df = mTmpDisplayFrame;
        final Rect of = mTmpOverscanFrame;
        final Rect cf = mTmpContentFrame;
        final Rect vf = mTmpVisibleFrame;
        final Rect dcf = mTmpDecorFrame;
        final Rect sf = mTmpStableFrame;
        Rect osf = null;
        dcf.setEmpty();
        .......
        if (layoutInScreen && layoutInsetDecor) {
            if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle()
                        + "): IN_SCREEN, INSET_DECOR");
            ......
        }
        .....
        //zhoujinjian
        if ("com.android.testred".equals(win.getAttrs().packageName)) {
           pf.left = df.left = of.left = cf.left = displayFrames.mOverscan.left;
           pf.top = df.top = of.top = cf.top = displayFrames.mOverscan.top;
           pf.right = df.right = of.right = cf.right
                   = displayFrames.mOverscan.left + displayFrames.mOverscan.right / 3;
           pf.bottom = df.bottom = of.bottom = cf.bottom
                   = displayFrames.mOverscan.top + displayFrames.mOverscan.bottom;
        }

        //zhoujinjian
        if ("com.android.testgreen".equals(win.getAttrs().packageName)) {
           pf.left = df.left = of.left = cf.left = displayFrames.mOverscan.left  + displayFrames.mOverscan.right / 3;
           pf.top = df.top = of.top = cf.top = displayFrames.mOverscan.top;
           pf.right = df.right = of.right = cf.right
                   = displayFrames.mOverscan.left  + displayFrames.mOverscan.right * 2 / 3;
           pf.bottom = df.bottom = of.bottom = cf.bottom
                   = displayFrames.mOverscan.top + displayFrames.mOverscan.bottom;
        }

        //zhoujinjian
        if ("com.android.testblue".equals(win.getAttrs().packageName)) {
           pf.left = df.left = of.left = cf.left = displayFrames.mOverscan.left  + displayFrames.mOverscan.right * 2 / 3;
           pf.top = df.top = of.top = cf.top = displayFrames.mOverscan.top;
           pf.right = df.right = of.right = cf.right
                   = displayFrames.mOverscan.left  + displayFrames.mOverscan.right * 3 / 3;
           pf.bottom = df.bottom = of.bottom = cf.bottom
                   = displayFrames.mOverscan.top + displayFrames.mOverscan.bottom;
        }

----------------------------------------------------------------
对应Log:
......
04-16 13:08:37.002 V/WindowManager( 1049): layoutWindowLw(com.android.testred/com.android.testred.TestActivity): IN_SCREEN, INSET_DECOR
04-16 13:08:37.002 V/WindowManager( 1049): Compute frame com.android.testred/com.android.testred.TestActivity: sim=#120 attach=null type=1 flags=0x01810100 pf=[0,0][160,854] df=[0,0][160,854] of=[0,0][160,854] cf=[0,0][160,854] vf=[0,36][480,782] dcf=[0,36][480,782] sf=[0,36][480,782] osf=null


----------------------------------------------------------------
        if (DEBUG_LAYOUT) Slog.v(TAG, "Compute frame " + attrs.getTitle()
                + ": sim=#" + Integer.toHexString(sim)
                + " attach=" + attached + " type=" + type
                + String.format(" flags=0x%08x", fl)
                + " pf=" + pf.toShortString() + " df=" + df.toShortString()
                + " of=" + of.toShortString()
                + " cf=" + cf.toShortString() + " vf=" + vf.toShortString()
                + " dcf=" + dcf.toShortString()
                + " sf=" + sf.toShortString()
                + " osf=" + (osf == null ? "null" : osf.toShortString()));

        win.computeFrameLw(pf, df, of, cf, vf, dcf, sf, osf, displayFrames.mDisplayCutout,
                parentFrameWasClippedByDisplayCutout);
        // Dock windows carve out the bottom of the screen, so normal windows
        // can't appear underneath them.
        if (type == TYPE_INPUT_METHOD && win.isVisibleLw()
                && !win.getGivenInsetsPendingLw()) {
            setLastInputMethodWindowLw(null, null);
            offsetInputMethodWindowLw(win, displayFrames);
        }
        if (type == TYPE_VOICE_INTERACTION && win.isVisibleLw()
                && !win.getGivenInsetsPendingLw()) {
            offsetVoiceInputWindowLw(win, displayFrames);
        }
    }
1.2.2.5、WindowState.computeFrameLw()

WindowState大小复杂计算。

    @Override
    public void computeFrameLw(Rect parentFrame, Rect displayFrame, Rect overscanFrame,
            Rect contentFrame, Rect visibleFrame, Rect decorFrame, Rect stableFrame,
            Rect outsetFrame, WmDisplayCutout displayCutout,
            boolean parentFrameWasClippedByDisplayCutout) {
        ......
        mHaveFrame = true;
        mParentFrameWasClippedByDisplayCutout = parentFrameWasClippedByDisplayCutout;

        final Task task = getTask();
        final boolean inFullscreenContainer = inFullscreenContainer();
        final boolean windowsAreFloating = task != null && task.isFloating();
        final DisplayContent dc = getDisplayContent();

        ......

        final int pw = mContainingFrame.width();
        final int ph = mContainingFrame.height();
        ......

        mOverscanFrame.set(overscanFrame);
        mContentFrame.set(contentFrame);
        mVisibleFrame.set(visibleFrame);
        mDecorFrame.set(decorFrame);
        mStableFrame.set(stableFrame);
        final boolean hasOutsets = outsetFrame != null;
        if (hasOutsets) {
            mOutsetFrame.set(outsetFrame);
        }

        final int fw = mFrame.width();
        final int fh = mFrame.height();

        applyGravityAndUpdateFrame(layoutContainingFrame, layoutDisplayFrame);
        ......
        if (windowsAreFloating && !mFrame.isEmpty()) {
            ......
        } else {
            mContentFrame.set(Math.max(mContentFrame.left, mFrame.left),
                    Math.max(mContentFrame.top, mFrame.top),
                    Math.min(mContentFrame.right, mFrame.right),
                    Math.min(mContentFrame.bottom, mFrame.bottom));

            mVisibleFrame.set(Math.max(mVisibleFrame.left, mFrame.left),
                    Math.max(mVisibleFrame.top, mFrame.top),
                    Math.min(mVisibleFrame.right, mFrame.right),
                    Math.min(mVisibleFrame.bottom, mFrame.bottom));

            mStableFrame.set(Math.max(mStableFrame.left, mFrame.left),
                    Math.max(mStableFrame.top, mFrame.top),
                    Math.min(mStableFrame.right, mFrame.right),
                    Math.min(mStableFrame.bottom, mFrame.bottom));
        }

        ......
        if (mAttrs.type == TYPE_DOCK_DIVIDER) {
            ......
        } else {
            getDisplayContent().getBounds(mTmpRect);
            // Override right and/or bottom insets in case if the frame doesn't fit the screen in
            // non-fullscreen mode.
            boolean overrideRightInset = !windowsAreFloating && !inFullscreenContainer
                    && mFrame.right > mTmpRect.right;
            boolean overrideBottomInset = !windowsAreFloating && !inFullscreenContainer
                    && mFrame.bottom > mTmpRect.bottom;
            mContentInsets.set(mContentFrame.left - mFrame.left,
                    mContentFrame.top - mFrame.top,
                    overrideRightInset ? mTmpRect.right - mContentFrame.right
                            : mFrame.right - mContentFrame.right,
                    overrideBottomInset ? mTmpRect.bottom - mContentFrame.bottom
                            : mFrame.bottom - mContentFrame.bottom);

            mVisibleInsets.set(mVisibleFrame.left - mFrame.left,
                    mVisibleFrame.top - mFrame.top,
                    overrideRightInset ? mTmpRect.right - mVisibleFrame.right
                            : mFrame.right - mVisibleFrame.right,
                    overrideBottomInset ? mTmpRect.bottom - mVisibleFrame.bottom
                            : mFrame.bottom - mVisibleFrame.bottom);

            mStableInsets.set(Math.max(mStableFrame.left - mFrame.left, 0),
                    Math.max(mStableFrame.top - mFrame.top, 0),
                    overrideRightInset ? Math.max(mTmpRect.right - mStableFrame.right, 0)
                            : Math.max(mFrame.right - mStableFrame.right, 0),
                    overrideBottomInset ? Math.max(mTmpRect.bottom - mStableFrame.bottom, 0)
                            :  Math.max(mFrame.bottom - mStableFrame.bottom, 0));
        }

        mDisplayCutout = displayCutout.calculateRelativeTo(mFrame);

        // Offset the actual frame by the amount layout frame is off.
        mFrame.offset(-layoutXDiff, -layoutYDiff);
        mCompatFrame.offset(-layoutXDiff, -layoutYDiff);
        mContentFrame.offset(-layoutXDiff, -layoutYDiff);
        mVisibleFrame.offset(-layoutXDiff, -layoutYDiff);
        mStableFrame.offset(-layoutXDiff, -layoutYDiff);

        mCompatFrame.set(mFrame);
        ......
----------------------------------------------------------------
对应Log:
04-16 13:08:37.002 V/WindowState( 1049): Resolving (mRequestedWidth=160, mRequestedheight=854) to (pw=160, ph=854): frame=[0,0][160,854] ci=[0,0][0,0] vi=[0,36][0,72] si=[0,36][0,72] of=[0,0][0,0]

----------------------------------------------------------------
        if (DEBUG_LAYOUT || localLOGV) Slog.v(TAG,
                "Resolving (mRequestedWidth="
                + mRequestedWidth + ", mRequestedheight="
                + mRequestedHeight + ") to" + " (pw=" + pw + ", ph=" + ph
                + "): frame=" + mFrame.toShortString()
                + " ci=" + mContentInsets.toShortString()
                + " vi=" + mVisibleInsets.toShortString()
                + " si=" + mStableInsets.toShortString()
                + " of=" + mOutsets.toShortString());
    }

继续看看DisplayContent方法中的RootWindowContainer.performSurfacePlacement(recoveringMemory)

1.2.3、surfacePlacer.handleAppTransitionReadyLocked()
G:\android9.0\frameworks\base\services\core\java\com\android\server\wm\WindowSurfacePlacer.java

    int handleAppTransitionReadyLocked() {
        int appsCount = mService.mOpeningApps.size();
        if (!transitionGoodToGo(appsCount, mTempTransitionReasons)) {
            return 0;
        }

    private boolean transitionGoodToGo(int appsCount, SparseIntArray outReasons) {
        if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
                "Checking " + appsCount + " opening apps (frozen="
                        + mService.mDisplayFrozen + " timeout="
                        + mService.mAppTransition.isTimeout() + ")...");
        final ScreenRotationAnimation screenRotationAnimation =
            mService.mAnimator.getScreenRotationAnimationLocked(
                    Display.DEFAULT_DISPLAY);

        outReasons.clear();
        if (!mService.mAppTransition.isTimeout()) {
           ......
----------------------------------------------------------------
对应Log:
04-16 13:08:37.009 V/WindowSurfacePlacer( 1049): Checking 1 opening apps (frozen=false timeout=false)...
04-16 13:08:37.009 V/WindowSurfacePlacer( 1049): Check opening app=AppWindowToken{1579134 token=Token{ce2ac07 ActivityRecord{65cc87a u0 com.android.testred/.TestActivity t5}}}: allDrawn=false startingDisplayed=false startingMoved=false isRelaunching()=false startingWindow=null
----------------------------------------------------------------
            for (int i = 0; i < appsCount; i++) {
                AppWindowToken wtoken = mService.mOpeningApps.valueAt(i);
                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
                        "Check opening app=" + wtoken + ": allDrawn="
                        + wtoken.allDrawn + " startingDisplayed="
                        + wtoken.startingDisplayed + " startingMoved="
                        + wtoken.startingMoved + " isRelaunching()="
                        + wtoken.isRelaunching() + " startingWindow="
                        + wtoken.startingWindow);


                final boolean allDrawn = wtoken.allDrawn && !wtoken.isRelaunching();
                if (!allDrawn && !wtoken.startingDisplayed && !wtoken.startingMoved) {
                    return false;
                }
                final int windowingMode = wtoken.getWindowingMode();
                if (allDrawn) {
                    outReasons.put(windowingMode,  APP_TRANSITION_WINDOWS_DRAWN);
                } else {
                    outReasons.put(windowingMode,
                            wtoken.startingData instanceof SplashScreenStartingData
                                    ? APP_TRANSITION_SPLASH_SCREEN
                                    : APP_TRANSITION_SNAPSHOT);
                }
            }

           ......
        }
        return true;
    }

根据前面分析可知道,现在App(com.android.testred)的大小和布局都处理好了,等待显示,但现在还么有mDrawState=NO_SURFACE ,肯定无法显示出来的,接下来看看Surface创建过程。

04-16 13:08:37.007 V/AppWindowToken( 1049): Eval win Window{c1255cd u0 com.android.testred/com.android.testred.TestActivity}: isDrawn=false, isAnimationSet=true
04-16 13:08:37.007 V/AppWindowToken( 1049): Not displayed: s=null pv=true mDrawState=NO_SURFACE ph=false th=false a=true

继续看看WindowManagerService.relayoutWindow()

(2)、Surface创建过程
G:\android9.0\frameworks\base\services\core\java\com\android\server\wm\WindowManagerService.java

    private int createSurfaceControl(Surface outSurface, int result, WindowState win,
            WindowStateAnimator winAnimator) {
        if (!win.mHasSurface) {
            result |= RELAYOUT_RES_SURFACE_CHANGED;
        }

        WindowSurfaceController surfaceController;
        try {
            Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "createSurfaceControl");
            surfaceController = winAnimator.createSurfaceLocked(win.mAttrs.type, win.mOwnerUid);
        } finally {
            Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
        }
        if (surfaceController != null) {
            surfaceController.getSurface(outSurface);
            if (SHOW_TRANSACTIONS) Slog.i(TAG_WM, "  OUT SURFACE " + outSurface + ": 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);
            outSurface.release();
        }

        return result;
    }
2.1、winAnimator.createSurfaceLocked()
G:\android9.0\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");
----------------------------------------------------------------
对应Log:
04-16 13:08:37.010 I/WindowStateAnimator( 1049): createSurface WindowStateAnimator{4fb81c9 com.android.testred/com.android.testred.TestActivity}: mDrawState=DRAW_PENDING
----------------------------------------------------------------
        resetDrawState();

        mService.makeWindowFreezingScreenIfNeededLocked(w);

        int flags = SurfaceControl.HIDDEN;//设置flags 为 HIDDEN
        final WindowManager.LayoutParams attrs = w.mAttrs;

        if (mService.isSecureLocked(w)) {
            flags |= SurfaceControl.SECURE;
        }

        mTmpSize.set(0, 0, 0, 0);
        //计算Surface大小
        calculateSurfaceBounds(w, attrs);
        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);
        }
----------------------------------------------------------------
对应Log:
04-16 13:08:37.010 V/WindowStateAnimator( 1049): Creating surface in session android.view.SurfaceSession@3812e82 window WindowStateAnimator{4fb81c9 com.android.testred/com.android.testred.TestActivity} w=160 h=854 x=0 y=0 format=-2 flags=4

----------------------------------------------------------------
        // 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 = new WindowSurfaceController(mSession.mSurfaceSession,
                    attrs.getTitle().toString(), width, height, format, flags, this,
                    windowType, ownerUid);

            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);
            }


----------------------------------------------------------------
对应Log:
04-16 13:08:37.012 I/WindowStateAnimator( 1049):   CREATE SURFACE Surface(name=com.android.testred/com.android.testred.TestActivity)/@0xb17b0ce IN SESSION android.view.SurfaceSession@3812e82: pid=2602 format=-2 flags=0x4 / WindowStateAnimator{4fb81c9 com.android.testred/com.android.testred.TestActivity}
----------------------------------------------------------------
        } 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.mFrame.left + " top=" + w.mFrame.top
                + ", animLayer=" + mAnimLayer);
----------------------------------------------------------------
对应Log:
04-16 13:08:37.012 V/WindowStateAnimator( 1049): Got surface: Surface(name=com.android.testred/com.android.testred.TestActivity)/@0xb17b0ce, set left=0 top=0, animLayer=0
----------------------------------------------------------------
        if (SHOW_LIGHT_TRANSACTIONS) {
            Slog.i(TAG, ">>> OPEN TRANSACTION createSurfaceLocked");
            WindowManagerService.logSurface(w, "CREATE pos=("
                    + w.mFrame.left + "," + w.mFrame.top + ") ("
                    + width + "x" + height + "), layer=" + mAnimLayer + " HIDE", false);
        }

        mLastHidden = true;

        if (WindowManagerService.localLOGV) Slog.v(TAG, "Created surface " + this);
----------------------------------------------------------------
对应Log:
04-16 13:08:37.012 I/WindowStateAnimator( 1049): >>> OPEN TRANSACTION createSurfaceLocked
04-16 13:08:37.012 I/WindowManager( 1049):   SURFACE CREATE pos=(0,0) (160x854), layer=0 HIDE: Window{c1255cd u0 com.android.testred/com.android.testred.TestActivity}
04-16 13:08:37.012 V/WindowStateAnimator( 1049): Created surface WindowStateAnimator{4fb81c9 com.android.testred/com.android.testred.TestActivity}
----------------------------------------------------------------
        return mSurfaceController;
    }
2.1.1、new WindowSurfaceController()
G:\android9.0\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) {
        mAnimator = animator;

        mSurfaceW = w;
        mSurfaceH = h;

        title = name;

        mService = animator.mService;
        final WindowState win = animator.mWin;
        mWindowType = windowType;
        mWindowSession = win.mSession;

        Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "new SurfaceControl");
        final SurfaceControl.Builder b = win.makeSurface()
                .setParent(win.getSurfaceControl())
                .setName(name)
                .setSize(w, h)
                .setFormat(format)
                .setFlags(flags)
                .setMetadata(windowType, ownerUid);
        mSurfaceControl = b.build();
        Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
    }
2.1.1.1、创建SurfaceControl build()
G:\android9.0\frameworks\base\core\java\android\view\SurfaceControl.java

        public SurfaceControl build() {
            if (mWidth <= 0 || mHeight <= 0) {
                throw new IllegalArgumentException(
                        "width and height must be set");
            }
            return new SurfaceControl(mSession, mName, mWidth, mHeight, mFormat,
                    mFlags, mParent, mWindowType, mOwnerUid);
        }
2.1.1.2、new SurfaceControl()
    /**
     * Create a surface with a name.
     * <p>
     * The surface creation flags specify what kind of surface to create and
     * certain options such as whether the surface can be assumed to be opaque
     * and whether it should be initially hidden.  Surfaces should always be
     * created with the {@link #HIDDEN} flag set to ensure that they are not
     * made visible prematurely before all of the surface's properties have been
     * configured.
     * <p>
     * Good practice is to first create the surface with the {@link #HIDDEN} flag
     * specified, open a transaction, set the surface layer, layer stack, alpha,
     * and position, call {@link #show} if appropriate, and close the transaction.
     *
     * @param session The surface session, must not be null.
     * @param name The surface name, must not be null.
     * @param w The surface initial width.
     * @param h The surface initial height.
     * @param flags The surface creation flags.  Should always include {@link #HIDDEN}
     * in the creation flags.
     * @param windowType The type of the window as specified in WindowManager.java.
     * @param ownerUid A unique per-app ID.
     *
     * @throws throws OutOfResourcesException If the SurfaceControl cannot be created.
     */
    private SurfaceControl(SurfaceSession session, String name, int w, int h, int format, int flags,
            SurfaceControl parent, int windowType, int ownerUid)
                    throws OutOfResourcesException, IllegalArgumentException {
        ......

        if ((flags & SurfaceControl.HIDDEN) == 0) {
            Log.w(TAG, "Surfaces should always be created with the HIDDEN flag set "
                    + "to ensure that they are not made visible prematurely before "
                    + "all of the surface's properties have been configured.  "
                    + "Set the other properties and make the surface visible within "
                    + "a transaction.  New surface name: " + name,
                    new Throwable());
        }

        mName = name;
        mWidth = w;
        mHeight = h;
        mNativeObject = nativeCreate(session, name, w, h, format, flags,
            parent != null ? parent.mNativeObject : 0, windowType, ownerUid);
        ......
        mCloseGuard.open("release");
    }



G:\android9.0\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,
        jint windowType, jint ownerUid) {
    ScopedUtfChars name(env, nameStr);
    sp<SurfaceComposerClient> client(android_view_SurfaceSession_getClient(env, sessionObj));
    SurfaceControl *parent = reinterpret_cast<SurfaceControl*>(parentObject);
    sp<SurfaceControl> surface;
    status_t err = client->createSurfaceChecked(
            String8(name.c_str()), w, h, format, &surface, flags, parent, windowType, ownerUid);
    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());
}

该函数首先得到前面创建好的SurfaceComposerClient对象,通过该对象向SurfaceFlinger端的Client对象发送创建Surface的请求,最后得到一个SurfaceControl对象
看看createSurfaceChecked()函数实现

G:\android9.0\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,
        int32_t windowType,
        int32_t ownerUid)
{
    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,
                windowType, ownerUid, &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;
}


G:\android9.0\frameworks\native\libs\gui\SurfaceControl.cpp
SurfaceControl::SurfaceControl(
        const sp<SurfaceComposerClient>& client,
        const sp<IBinder>& handle,
        const sp<IGraphicBufferProducer>& gbp,
        bool owned)
    : mClient(client), mHandle(handle), mGraphicBufferProducer(gbp), mOwned(owned)
{
}

SurfaceComposerClient将Surface创建请求转交给保存在其成员变量中的Bp SurfaceComposerClient对象来完成,在SurfaceFlinger端的Client本地对象会返回一个ISurface代理对象给应用程序,通过该代理对象为应用程序当前创建的Surface创建一个SurfaceControl对象。 [ISurfaceComposerClient.cpp]

G:\android9.0\frameworks\native\libs\gui\ISurfaceComposerClient.cpp
    status_t createSurface(const String8& name, uint32_t width, uint32_t height, PixelFormat format,
                           uint32_t flags, const sp<IBinder>& parent, int32_t windowType,
                           int32_t ownerUid, sp<IBinder>* handle,
                           sp<IGraphicBufferProducer>* gbp) override {
        return callRemote<decltype(&ISurfaceComposerClient::createSurface)>(Tag::CREATE_SURFACE,
                                                                            name, width, height,
                                                                            format, flags, parent,
                                                                            windowType, ownerUid,
                                                                            handle, gbp);
    }
2.1.1.3、Client->createSurface()

MessageCreateSurface消息是专门为应用程序请求创建Surface而定义的一种消息类型:

G:\android9.0\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, int32_t windowType, int32_t ownerUid,
        sp<IBinder>* handle,
        sp<IGraphicBufferProducer>* gbp)
{
    sp<Layer> parent = nullptr;
    if (parentHandle != nullptr) {
        auto layerHandle = reinterpret_cast<Layer::Handle*>(parentHandle.get());
        parent = layerHandle->owner.promote();
        if (parent == nullptr) {
            return NAME_NOT_FOUND;
        }
    }
    if (parent == nullptr) {
        bool parentDied;
        parent = getParentLayer(&parentDied);
        // If we had a parent, but it died, we've lost all
        // our capabilities.
        if (parentDied) {
            return NAME_NOT_FOUND;
        }
    }

    /*
     * createSurface must be called from the GL thread so that it can
     * have access to the GL context.
     */
    class MessageCreateLayer : public MessageBase {
        SurfaceFlinger* flinger;
        Client* client;
        sp<IBinder>* handle;
        sp<IGraphicBufferProducer>* gbp;
        status_t result;
        const String8& name;
        uint32_t w, h;
        PixelFormat format;
        uint32_t flags;
        sp<Layer>* parent;
        int32_t windowType;
        int32_t ownerUid;
    public:
        MessageCreateLayer(SurfaceFlinger* flinger,
                const String8& name, Client* client,
                uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
                sp<IBinder>* handle, int32_t windowType, int32_t ownerUid,
                sp<IGraphicBufferProducer>* gbp,
                sp<Layer>* parent)
            : flinger(flinger), client(client),
              handle(handle), gbp(gbp), result(NO_ERROR),
              name(name), w(w), h(h), format(format), flags(flags),
              parent(parent), windowType(windowType), ownerUid(ownerUid) {
        }
        status_t getResult() const { return result; }
        virtual bool handler() {
            result = flinger->createLayer(name, client, w, h, format, flags,
                    windowType, ownerUid, handle, gbp, parent);
            return true;
        }
    };

    sp<MessageBase> msg = new MessageCreateLayer(mFlinger.get(),
            name, this, w, h, format, flags, handle,
            windowType, ownerUid, gbp, &parent);
    mFlinger->postMessageSync(msg);
    return static_cast<MessageCreateLayer*>( msg.get() )->getResult();
}

SurfaceFlinger根据标志位创建对应类型的Surface,当前系统定义了2种类型的Layer

G:\android9.0\frameworks\native\libs\gui\include\gui\ISurfaceComposerClient.h

        eFXSurfaceNormal = 0x00000000,//正常surface
        eFXSurfaceColor = 0x00020000,//只有颜色数据surface
G:\android9.0\frameworks\native\services\surfaceflinger\SurfaceFlinger.cpp

status_t SurfaceFlinger::createLayer(
        const String8& name,
        const sp<Client>& client,
        uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
        int32_t windowType, int32_t ownerUid, sp<IBinder>* handle,
        sp<IGraphicBufferProducer>* gbp, sp<Layer>* parent)
{
    if (int32_t(w|h) < 0) {
        ALOGE("createLayer() failed, w or h is negative (w=%d, h=%d)",
                int(w), int(h));
        return BAD_VALUE;
    }

    status_t result = NO_ERROR;

    sp<Layer> layer;

    String8 uniqueName = getUniqueLayerName(name);

    switch (flags & ISurfaceComposerClient::eFXSurfaceMask) {
        case ISurfaceComposerClient::eFXSurfaceNormal:
            result = createBufferLayer(client,
                    uniqueName, w, h, flags, format,
                    handle, gbp, &layer);

            break;
        case ISurfaceComposerClient::eFXSurfaceColor:
            result = createColorLayer(client,
                    uniqueName, w, h, flags,
                    handle, &layer);
            break;
        default:
            result = BAD_VALUE;
            break;
    }

    if (result != NO_ERROR) {
        return result;
    }

    // window type is WINDOW_TYPE_DONT_SCREENSHOT from SurfaceControl.java
    // TODO b/64227542
    if (windowType == 441731) {
        windowType = 2024; // TYPE_NAVIGATION_BAR_PANEL
        layer->setPrimaryDisplayOnly();
    }

    layer->setInfo(windowType, ownerUid);

    result = addClientLayer(client, *handle, *gbp, layer, *parent);
    if (result != NO_ERROR) {
        return result;
    }
    mInterceptor->saveSurfaceCreation(layer);

    setTransactionFlags(eTransactionNeeded);
    return result;
}

有前面java层可知flags = SurfaceControl.HIDDEN,flags & ISurfaceComposerClient::eFXSurfaceMask == eFXSurfaceNormal = 0x00000000,所以此外走createBufferLayer()分支

2.1.1.4、createBufferLayer()
G:\android9.0\frameworks\native\services\surfaceflinger\SurfaceFlinger.cpp

status_t SurfaceFlinger::createBufferLayer(const sp<Client>& client,
        const String8& name, uint32_t w, uint32_t h, uint32_t flags, PixelFormat& format,
        sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp, sp<Layer>* outLayer)
{
    // initialize the surfaces
    switch (format) {
    case PIXEL_FORMAT_TRANSPARENT:
    case PIXEL_FORMAT_TRANSLUCENT:
        format = PIXEL_FORMAT_RGBA_8888;
        break;
    case PIXEL_FORMAT_OPAQUE:
        format = PIXEL_FORMAT_RGBX_8888;
        break;
    }

    sp<BufferLayer> layer = DisplayUtils::getInstance()->getBufferLayerInstance(
                            this, client, name, w, h, flags);
    status_t err = layer->setBuffers(w, h, format, flags);
----------------------------------------------------------------
对应Log:

status_t BufferLayer::setBuffers(uint32_t w, uint32_t h, PixelFormat format, uint32_t flags) {
    uint32_t const maxSurfaceDims =
            min(mFlinger->getMaxTextureSize(), mFlinger->getMaxViewportDims());

    // never allow a surface larger than what our underlying GL implementation
    // can handle.
    if ((uint32_t(w) > maxSurfaceDims) || (uint32_t(h) > maxSurfaceDims)) {
        ALOGE("dimensions too large %u x %u", uint32_t(w), uint32_t(h));
        return BAD_VALUE;
    }

    mFormat = format;

    mPotentialCursor = (flags & ISurfaceComposerClient::eCursorWindow) ? true : false;
    mProtectedByApp = (flags & ISurfaceComposerClient::eProtectedByApp) ? true : false;
    mCurrentOpacity = getOpacityForFormat(format);

    mConsumer->setDefaultBufferSize(w, h);
    mConsumer->setDefaultBufferFormat(format);
    mConsumer->setConsumerUsageBits(getEffectiveUsage(0));

    return NO_ERROR;
}

04-16 13:08:37.011 V/BufferQueueConsumer(  739): [com.android.testred/com.android.testred.TestActivity#0] setDefaultBufferSize: width=160 height=854
04-16 13:08:37.011 V/BufferQueueConsumer(  739): [com.android.testred/com.android.testred.TestActivity#0] setDefaultBufferFormat: 1
04-16 13:08:37.011 V/BufferQueueConsumer(  739): [com.android.testred/com.android.testred.TestActivity#0] setConsumerUsageBits: 0x900
----------------------------------------------------------------
    if (err == NO_ERROR) {
        *handle = layer->getHandle();
        *gbp = layer->getProducer();
        *outLayer = layer;
    }

    ALOGE_IF(err, "createBufferLayer() failed (%s)", strerror(-err));
    return err;
}
2.1.1.5、DisplayUtils::getInstance()->getBufferLayerInstance()
G:\android9.0\frameworks\native\services\surfaceflinger\DisplayUtils.cpp

BufferLayer* DisplayUtils::getBufferLayerInstance(SurfaceFlinger* flinger,
                            const sp<Client>& client, const String8& name,
                            uint32_t w, uint32_t h, uint32_t flags) {
    if (sUseExtendedImpls) {
        return new ExBufferLayer(flinger, client, name, w, h, flags);
    } else {
        return new BufferLayer(flinger, client, name, w, h, flags);
    }
}
2.1.1.6、new BufferLayer()
G:\android9.0\frameworks\native\services\surfaceflinger\BufferLayer.cpp

BufferLayer::BufferLayer(SurfaceFlinger* flinger, const sp<Client>& client, const String8& name,
                         uint32_t w, uint32_t h, uint32_t flags)
      : Layer(flinger, client, name, w, h, flags),
        mConsumer(nullptr),
        mTextureName(UINT32_MAX),
        mFormat(PIXEL_FORMAT_NONE),
        mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
        mBufferLatched(false),
        mPreviousFrameNumber(0),
        mUpdateTexImageFailed(false),
        mRefreshPending(false) {
    ALOGV("Creating Layer %s", name.string());
----------------------------------------------------------------
对应Log:
04-16 13:08:37.011 V/BufferLayer(  739): Creating Layer com.android.testred/com.android.testred.TestActivity#0
----------------------------------------------------------------
    //生成Textures并初始化
    mFlinger->getRenderEngine().genTextures(1, &mTextureName);
    mTexture.init(Texture::TEXTURE_EXTERNAL, mTextureName);

    if (flags & ISurfaceComposerClient::eNonPremultiplied) mPremultipliedAlpha = false;

    mCurrentState.requested = mCurrentState.active;

    // drawing state & current state are identical
    mDrawingState = mCurrentState;
}

回到SurfaceComposerClient.cpp中
继续看看,根据回传的 sp handle和 sp gbp 创建SurfaceControl
outSurface = new SurfaceControl(this, handle, gbp, true / owned */)

然后android_view_SurfaceControl.cpp nativeCreate()函数中将 reinterpret_cast(surface.get()) 的地址返回给Java层。

2.1.1.7、BufferLayer->onFirstRef()

第一次强引用Layer对象时,onFirstRef()函数被回调

G:\android9.0\frameworks\native\services\surfaceflinger\BufferLayer.cpp
void BufferLayer::onFirstRef() {
    // Creates a custom BufferQueue for SurfaceFlingerConsumer to use
    sp<IGraphicBufferProducer> producer;
    sp<IGraphicBufferConsumer> consumer;
    BufferQueue::createBufferQueue(&producer, &consumer, true);
    mProducer = new MonitoredProducer(producer, mFlinger, this);
    mConsumer = new BufferLayerConsumer(consumer,
            mFlinger->getRenderEngine(), mTextureName, this);


----------------------------------------------------------------
对应Log:
04-16 13:08:37.011 V/BufferQueueConsumer(  739): [unnamed-739-40] setConsumerUsageBits: 0x900
04-16 13:08:37.011 V/ConsumerBase(  739): [unnamed-739-40] setFrameAvailableListener
04-16 13:08:37.011 V/BufferQueueConsumer(  739): [unnamed-739-40] setConsumerName: 'com.android.testred/com.android.testred.TestActivity#0'
04-16 13:08:37.011 V/BufferQueueProducer(  739): [] setMaxDequeuedBufferCount: maxDequeuedBuffers = 2
----------------------------------------------------------------
    mConsumer->setConsumerUsageBits(getEffectiveUsage(0));
    mConsumer->setContentsChangedListener(this);
    mConsumer->setName(mName);

    if (mFlinger->isLayerTripleBufferingDisabled()) {
        mProducer->setMaxDequeuedBufferCount(2);
    }

    const sp<const DisplayDevice> hw(mFlinger->getDefaultDisplayDevice());
----------------------------------------------------------------
对应Log:
04-16 13:08:37.011 V/BufferQueueConsumer(  739): [com.android.testred/com.android.testred.TestActivity#0] setTransformHint: 0
----------------------------------------------------------------
    updateTransformHint(hw);
}


enter image description here

2.1.1.8、BufferQueue::createBufferQueue()

所以核心都是这个BufferQueueCore,他是管理图形缓冲区的中枢。

G:\android9.0\frameworks\native\libs\gui\BufferQueue.cpp
void BufferQueue::createBufferQueue(sp<IGraphicBufferProducer>* outProducer,
        sp<IGraphicBufferConsumer>* outConsumer,
        bool consumerIsSurfaceFlinger) {
    ......
    sp<BufferQueueCore> core(new BufferQueueCore());
    sp<IGraphicBufferProducer> producer(new BufferQueueProducer(core, consumerIsSurfaceFlinger));

    sp<IGraphicBufferConsumer> consumer(new BufferQueueConsumer(core));
    *outProducer = producer;
    *outConsumer = consumer;
}


G:\android9.0\frameworks\native\libs\gui\BufferQueueCore.cpp
BufferQueueCore::BufferQueueCore() :
    ......
    mUniqueId(getUniqueId())
{
    int numStartingBuffers = getMaxBufferCountLocked();
    for (int s = 0; s < numStartingBuffers; s++) {
        mFreeSlots.insert(s);
    }
    //static constexpr int NUM_BUFFER_SLOTS = 64;
    for (int s = numStartingBuffers; s < BufferQueueDefs::NUM_BUFFER_SLOTS;
            s++) {
        mUnusedSlots.push_front(s);
    }
}
2.1.1.9、new BufferLayerConsumer()
G:\android9.0\frameworks\native\services\surfaceflinger\BufferLayerConsumer.cpp

BufferLayerConsumer::BufferLayerConsumer(const sp<IGraphicBufferConsumer>& bq,
                                         RE::RenderEngine& engine, uint32_t tex, Layer* layer)
      : ConsumerBase(bq, false),
        mCurrentCrop(Rect::EMPTY_RECT),
        mCurrentTransform(0),
        mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
        mCurrentFence(Fence::NO_FENCE),
        mCurrentTimestamp(0),
        mCurrentDataSpace(ui::Dataspace::UNKNOWN),
        mCurrentFrameNumber(0),
        mCurrentTransformToDisplayInverse(false),
        mCurrentSurfaceDamage(),
        mCurrentApi(0),
        mDefaultWidth(1),
        mDefaultHeight(1),
        mFilteringEnabled(true),
        mRE(engine),
        mTexName(tex),
        mLayer(layer),
        mCurrentTexture(BufferQueue::INVALID_BUFFER_SLOT) {
----------------------------------------------------------------
对应Log:
04-16 13:08:37.011 V/BufferLayerConsumer(  739): [unnamed-739-40] BufferLayerConsumer
----------------------------------------------------------------
    BLC_LOGV("BufferLayerConsumer");

    memcpy(mCurrentTransformMatrix, mtxIdentity.asArray(), sizeof(mCurrentTransformMatrix));
----------------------------------------------------------------
对应Log:
04-16 13:08:37.011 V/BufferQueueConsumer(  739): [unnamed-739-40] setConsumerUsageBits: 0x100
----------------------------------------------------------------
    mConsumer->setConsumerUsageBits(DEFAULT_USAGE_FLAGS);
}

BufferLayerConsumer会首先初始化ConsumerBase

2.1.1.10、ConsumerBase()

G:\android9.0\frameworks\native\libs\gui\ConsumerBase.cpp

ConsumerBase::ConsumerBase(const sp<IGraphicBufferConsumer>& bufferQueue, bool controlledByApp) :
        mAbandoned(false),
        mConsumer(bufferQueue),
        mPrevFinalReleaseFence(Fence::NO_FENCE) {
    // Choose a name using the PID and a process-unique ID.
    mName = String8::format("unnamed-%d-%d", getpid(), createProcessUniqueId());

    // Note that we can't create an sp<...>(this) in a ctor that will not keep a
    // reference once the ctor ends, as that would cause the refcount of 'this'
    // dropping to 0 at the end of the ctor.  Since all we need is a wp<...>
    // that's what we create.
    wp<ConsumerListener> listener = static_cast<ConsumerListener*>(this);
    sp<IConsumerListener> proxy = new BufferQueue::ProxyConsumerListener(listener);

----------------------------------------------------------------
对应Log:
04-16 13:08:37.011 V/BufferQueueConsumer(  739): [] connect: controlledByApp=false
04-16 13:08:37.011 V/BufferQueueConsumer(  739): [] setConsumerName: 'unnamed-739-40'
----------------------------------------------------------------

    status_t err = mConsumer->consumerConnect(proxy, controlledByApp);
    if (err != NO_ERROR) {
        CB_LOGE("ConsumerBase: error connecting to BufferQueue: %s (%d)",
                strerror(-err), err);
    } else {
        mConsumer->setConsumerName(mName);
    }
}

enter image description here

2.2、winAnimator.createSurfaceLocked()

饶了一大圈,现在Surface创建好了,现象看看如何传回App进程

G:\android9.0\frameworks\base\services\core\java\com\android\server\wm\WindowManagerService.java

private int createSurfaceControl(Surface outSurface, int result, WindowState win,
        WindowStateAnimator winAnimator) {
    if (!win.mHasSurface) {
        result |= RELAYOUT_RES_SURFACE_CHANGED;
    }

    WindowSurfaceController surfaceController;
    try {
        Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "createSurfaceControl");
        surfaceController = winAnimator.createSurfaceLocked(win.mAttrs.type, win.mOwnerUid);
    } finally {
        Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
    }
    if (surfaceController != null) {
        surfaceController.getSurface(outSurface);
----------------------------------------------------------------
对应Log:
04-16 13:08:37.012 I/WindowManager( 1049):   OUT SURFACE Surface(name=null)/@0xe493bef: copied
----------------------------------------------------------------
        if (SHOW_TRANSACTIONS) Slog.i(TAG_WM, "  OUT SURFACE " + outSurface + ": 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);
        outSurface.release();
    }

    return result;
}
2.2.1、surfaceController.getSurface(outSurface)
G:\android9.0\frameworks\base\services\core\java\com\android\server\wm\WindowSurfaceController.java

void getSurface(Surface outSurface) {
    outSurface.copyFrom(mSurfaceControl);
}
2.2.2、outSurface.copyFrom(mSurfaceControl)
G:\android9.0\frameworks\base\core\java\android\view\Surface.java

    public void copyFrom(SurfaceControl other) {
        ......
        long surfaceControlPtr = other.mNativeObject;
        .......
        long newNativeObject = nativeGetFromSurfaceControl(surfaceControlPtr);

        synchronized (mLock) {
            if (mNativeObject != 0) {
                nativeRelease(mNativeObject);
            }
            setNativeObjectLocked(newNativeObject);
        }
    }
2.2.3、nativeGetFromSurfaceControl()
G:\android9.0\frameworks\base\core\jni\android_view_Surface.cpp

static jlong nativeGetFromSurfaceControl(JNIEnv* env, jclass clazz,
        jlong surfaceControlNativeObj) {
    /*
     * This is used by the WindowManagerService just after constructing
     * a Surface and is necessary for returning the Surface reference to
     * the caller. At this point, we should only have a SurfaceControl.
     */

    sp<SurfaceControl> ctrl(reinterpret_cast<SurfaceControl *>(surfaceControlNativeObj));
    sp<Surface> surface(ctrl->getSurface());
    if (surface != NULL) {
        surface->incStrong(&sRefBaseOwner);
    }
    return reinterpret_cast<jlong>(surface.get());
}



G:\android9.0\frameworks\native\libs\gui\SurfaceControl.cpp

sp<Surface> SurfaceControl::generateSurfaceLocked() const
{
    // This surface is always consumed by SurfaceFlinger, so the
    // producerControlledByApp value doesn't matter; using false.
    mSurfaceData = new Surface(mGraphicBufferProducer, false);

    return mSurfaceData;
}

sp<Surface> SurfaceControl::getSurface() const
{
    Mutex::Autolock _l(mLock);
    if (mSurfaceData == 0) {
        return generateSurfaceLocked();
    }
    return mSurfaceData;
}
2.2.4、Nativie Surface创建过程
Surface::Surface(const sp<IGraphicBufferProducer>& bufferProducer, bool controlledByApp)
      : mGraphicBufferProducer(bufferProducer),
        mCrop(Rect::EMPTY_RECT),
        mBufferAge(0),
        mGenerationNumber(0),
        mSharedBufferMode(false),
        mAutoRefresh(false),
        mSharedBufferSlot(BufferItem::INVALID_BUFFER_SLOT),
        mSharedBufferHasBeenQueued(false),
        mQueriedSupportedTimestamps(false),
        mFrameTimestampsSupportsPresent(false),
        mEnableFrameTimestamps(false),
        mFrameEventHistory(std::make_unique<ProducerFrameEventHistory>()) {
    // Initialize the ANativeWindow function pointers.
    ANativeWindow::setSwapInterval  = hook_setSwapInterval;
    ANativeWindow::dequeueBuffer    = hook_dequeueBuffer;
    ANativeWindow::cancelBuffer     = hook_cancelBuffer;
    ANativeWindow::queueBuffer      = hook_queueBuffer;
    ANativeWindow::query            = hook_query;
    ANativeWindow::perform          = hook_perform;

    ANativeWindow::dequeueBuffer_DEPRECATED = hook_dequeueBuffer_DEPRECATED;
    ANativeWindow::cancelBuffer_DEPRECATED  = hook_cancelBuffer_DEPRECATED;
    ANativeWindow::lockBuffer_DEPRECATED    = hook_lockBuffer_DEPRECATED;
    ANativeWindow::queueBuffer_DEPRECATED   = hook_queueBuffer_DEPRECATED;

    const_cast<int&>(ANativeWindow::minSwapInterval) = 0;
    const_cast<int&>(ANativeWindow::maxSwapInterval) = 1;

    mReqWidth = 0;
    mReqHeight = 0;
    mReqFormat = 0;
    mReqUsage = 0;
    mTimestamp = NATIVE_WINDOW_TIMESTAMP_AUTO;
    mDataSpace = Dataspace::UNKNOWN;
    mScalingMode = NATIVE_WINDOW_SCALING_MODE_FREEZE;
    mTransform = 0;
    mStickyTransform = 0;
    mDefaultWidth = 0;
    mDefaultHeight = 0;
    mUserWidth = 0;
    mUserHeight = 0;
    mTransformHint = 0;
    mConsumerRunningBehind = false;
    mConnectedToCpu = false;
    mProducerControlledByApp = controlledByApp;
    mSwapIntervalZero = false;
}
2.2.5、Surface跨进程传递( WMS->App)writeToParcel()

得到真正的Surface后,[->IWindowSession$Stub.java]

      case 6:
         ......
         Surface _arg17 = new Surface();
         int _result2 = this.relayout(_arg0, _arg1, _arg25, _arg3, _arg4, _arg5, _arg62, _result4, _result7, _arg9, _arg10, _arg11, _arg12, _arg13, _arg14, _arg15, _arg16, _arg17);
         ......
         if(_arg17 != null) {
            reply.writeInt(1);
            _arg17.writeToParcel(reply, 1);
         } else {
            reply.writeInt(0);
         }
         return true;

WMS会首先通过writeToParcel()函数将Surface对象写入App 进程端

G:\android9.0\frameworks\base\core\java\android\view\Surface.java

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        if (dest == null) {
            throw new IllegalArgumentException("dest must not be null");
        }
        synchronized (mLock) {
            // NOTE: This must be kept synchronized with the native parceling code
            // in frameworks/native/libs/Surface.cpp
            dest.writeString(mName);
            dest.writeInt(mIsSingleBuffered ? 1 : 0);
            nativeWriteToParcel(mNativeObject, dest);
        }
        if ((flags & Parcelable.PARCELABLE_WRITE_RETURN_VALUE) != 0) {
            release();
        }
    }


G:\android9.0\frameworks\base\core\jni\android_view_Surface.cpp

static void nativeWriteToParcel(JNIEnv* env, jclass clazz,
        jlong nativeObject, jobject parcelObj) {
    Parcel* parcel = parcelForJavaObject(env, parcelObj);
    if (parcel == NULL) {
        doThrowNPE(env);
        return;
    }
    sp<Surface> self(reinterpret_cast<Surface *>(nativeObject));
    android::view::Surface surfaceShim;
    if (self != nullptr) {
        surfaceShim.graphicBufferProducer = self->getIGraphicBufferProducer();
    }
    // Calling code in Surface.java has already written the name of the Surface
    // to the Parcel
    surfaceShim.writeToParcel(parcel, /*nameAlreadyWritten*/true);
}
2.2.6、Surface跨进程传递( App->WMS)readFromParcel()

[->IWindowSession$Stub$Proxy.java]

  public int relayout(IWindow window, int seq, WindowManager.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 displayCutout, MergedConfiguration outMergedConfiguration, Surface outSurface) throws RemoteException {
    Parcel _data = Parcel.obtain();
    Parcel _reply = Parcel.obtain();
    try
{
   ......
   mRemote.transact(6, _d