Android應(yīng)用與SurfaceFlinger建立連接的過程

基于Android 9.0源碼分析

類圖

  • DecorView
    • Android窗口的頂級View
  • PhoneWindow
    • 代表Android窗口
  • WindowManagerImpl
    • 應(yīng)用通過該類與系統(tǒng)窗口管理服務(wù)通信,關(guān)聯(lián)特定的窗口
  • WindowManagerGlobal
    • 進(jìn)程全局對象,實現(xiàn)WindowManagerImpl與系統(tǒng)窗口管理服務(wù)的通信
  • ViewRootImpl
    • 實現(xiàn)了View與窗口管理之間的協(xié)議
  • Choreographer
    • Choreographer收到顯示子系統(tǒng)發(fā)送的Vsync信號后毒租,協(xié)調(diào)下一幀渲染中的動畫、輸入和繪制過程
  • FrameDisplayEventReceiver
    • 在應(yīng)用內(nèi)請求是整、接收顯示事件(Vsync信號等)
  • ISurfaceComposer
    • 定義訪問SurfaceFlinger的Binder IPC接口
  • BitTube
    • Socket的封裝,用于進(jìn)程間通信民假,可跨進(jìn)程傳遞

Android應(yīng)用與SurfaceFlinger建立連接的過程

Android應(yīng)用在執(zhí)行完Activity的onResume()后會建立與SurfaceFlinger的連接浮入,以便接受SurfaceFlinger發(fā)送的Vsync信號,下面從ActivityThreadhandleResumeActivity()開始分析羊异。

public void handleResumeActivity(IBinder token, boolean finalStateRequest, booleanisForward,
        String reason) {
    // If we are getting ready to gc after going to the background, well
    // we are back active so skip it.
    unscheduleGcIdler();
    mSomeActivitiesChanged = true;
    // TODO Push resumeArgs into the activity for consideration
    // 調(diào)用Activity的onResume的方法
    final ActivityClientRecord r = performResumeActivity(token, finalStateRequest, reason);
    if (r == null) {
        // We didn't actually resume the activity, so skipping any follow-up actions.
        return;
    }
    ......
    if (r.window == null && !a.mFinished && willBeVisible) {
        // PhoneWindow對象
        r.window = r.activity.getWindow();
        // DecorView對象
        View decor = r.window.getDecorView();
        decor.setVisibility(View.INVISIBLE);
        // wm為WindowManagerImpl對象
        ViewManager wm = a.getWindowManager();
        // 窗口布局參數(shù)
        WindowManager.LayoutParams l = r.window.getAttributes();
        // 設(shè)置Activity的DecorView
        a.mDecor = decor;
        l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
        l.softInputMode |= forwardBit;
        if (r.mPreserveWindow) {
            a.mWindowAdded = true;
            r.mPreserveWindow = false;
            // Normally the ViewRoot sets up callbacks with the Activity
            // in addView->ViewRootImpl#setView. If we are instead reusing
            // the decor view we have to notify the view root that the
            // callbacks may have changed.
            ViewRootImpl impl = decor.getViewRootImpl();
            if (impl != null) {
                impl.notifyChildRebuilt();
            }
        }
        // 通常mVisibleFromClient為true
        if (a.mVisibleFromClient) {
            // mWindowAdded這里為false
            if (!a.mWindowAdded) {
                a.mWindowAdded = true;
                // 設(shè)置DecorView的LayoutParams事秀,添加DecorView到Window
                wm.addView(decor, l);
            } else {
                // The activity will get a callback for this {@link LayoutParams} change
                // earlier. However, at that time the decor will not be set (this is set
                // in this method), so no action will be taken. This call ensures the
                // callback occurs with the decor set.
                a.onWindowAttributesChanged(l);
            }
        }
        // If the window has already been added, but during resume
        // we started another activity, then don't yet make the
        // window visible.
    } else if (!willBeVisible) {
        if (localLOGV) Slog.v(TAG, "Launch " + r + " mStartedActivity set");
        r.hideForNow = true;
    }
    ......
}

下面看WindowManagerImpladdView()的實現(xiàn)

public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
    // 設(shè)置params的token
    applyDefaultToken(params);
    // 調(diào)用WindowManagerGlobal的addView
    mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow);
}

public void addView(View view, ViewGroup.LayoutParams params,
        Display display, Window parentWindow) {
    // view為DecorView
    // params為DecorView關(guān)聯(lián)的LayoutParams
    // parentWindow為PhoneWindow
    if (view == null) {
        throw new IllegalArgumentException("view must not be null");
    }
    if (display == null) {
        throw new IllegalArgumentException("display must not be null");
    }
    if (!(params instanceof WindowManager.LayoutParams)) {
        throw new IllegalArgumentException("Params must be WindowManager.LayoutParams");
    }
    final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams) params;
    if (parentWindow != null) {
        // 設(shè)置LayoutParams的token、Title和包名等
        parentWindow.adjustLayoutParamsForSubWindow(wparams);
    } else {
        // If there's no parent, then hardware acceleration for this view is
        // set from the application's hardware acceleration setting.
        final Context context = view.getContext();
        if (context != null
                && (context.getApplicationInfo().flags
                        & ApplicationInfo.FLAG_HARDWARE_ACCELERATED) != 0) {
            wparams.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
        }
    }
    synchronized (mLock) {
        // Start watching for system property changes.
        // 監(jiān)聽系統(tǒng)屬性的改變野舶,觀察者模式
        if (mSystemPropertyUpdater == null) {
            mSystemPropertyUpdater = new Runnable() {
                @Override public void run() {
                    synchronized (mLock) {
                        for (int i = mRoots.size() - 1; i >= 0; --i) {
                            mRoots.get(i).loadSystemProperties();
                        }
                    }
                }
            };
            SystemProperties.addChangeCallback(mSystemPropertyUpdater);
        }
        // 查找DecorView
        int index = findViewLocked(view, false);
        if (index >= 0) {
            if (mDyingViews.contains(view)) {
                // Don't wait for MSG_DIE to make it's way through root's queue.
                mRoots.get(index).doDie();
            } else {
                throw new IllegalStateException("View " + view
                        + " has already been added to the window manager.");
            }
            // The previous removeView() had not completed executing. Now it has.
        }
        // If this is a panel window, then find the window it is being
        // attached to for future reference.
        if (wparams.type >= WindowManager.LayoutParams.FIRST_SUB_WINDOW &&
                wparams.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
            final int count = mViews.size();
            for (int i = 0; i < count; i++) {
                if (mRoots.get(i).mWindow.asBinder() == wparams.token) {
                    panelParentView = mViews.get(i);
                }
            }
        }
        // 創(chuàng)建ViewRootImpl
        root = new ViewRootImpl(view.getContext(), display);
        // 設(shè)置View布局參數(shù)
        view.setLayoutParams(wparams);
        // DecorView/ViewRootImpl/LayoutParams添加到WindowManagerGlobal
        mViews.add(view);
        mRoots.add(root);
        mParams.add(wparams);
        // do this last because it fires off messages to start doing things
        try {
            // 調(diào)用ViewRootImpl的setView()
            root.setView(view, wparams, panelParentView);
        } catch (RuntimeException e) {
            // BadTokenException or InvalidDisplayException, clean up.
            if (index >= 0) {
                removeViewLocked(index, true);
            }
            throw e;
        }
    }
}

ViewRootImpl的構(gòu)造方法中建立與SurfaceFlinger的連接易迹,下面看ViewRootImpl的構(gòu)造方法

public ViewRootImpl(Context context, Display display) {
    mContext = context;
    // mWindowSession為IWindowSession.Stub.Proxy對象,單例模式
    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();
    // 創(chuàng)建W對象平道,Binder服務(wù)對象
    // 用于接收WindowManager發(fā)送的應(yīng)用窗口感興趣的事件
    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;
    // 創(chuàng)建View.AttachInfo記錄添加到窗口的View的信息
    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);
    // 獲取Choreographer對象赴蝇,在Choreographer構(gòu)造函數(shù)中建立與SurfaceFlinger的連接
    mChoreographer = Choreographer.getInstance();
    mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
    if (!sCompatibilityDone) {
        sAlwaysAssignFocus = mTargetSdkVersion < Build.VERSION_CODES.P;
        sCompatibilityDone = true;
    }
    loadSystemProperties();
}

下面看ChoreographergetInstance()的實現(xiàn)

// Choreographer為ThreadLocal對象,關(guān)聯(lián)的線程必須有l(wèi)ooper
public static Choreographer getInstance() {
    // 調(diào)用initialValue()創(chuàng)建Choreographer
    return sThreadInstance.get();
}

private static final ThreadLocal<Choreographer> sThreadInstance =
        new ThreadLocal<Choreographer>() {
    @Override
    protected Choreographer initialValue() {
        Looper looper = Looper.myLooper();
        if (looper == null) {
            throw new IllegalStateException("The current thread must have a looper!");
        }
        Choreographer choreographer = new Choreographer(looper, VSYNC_SOURCE_APP);
        if (looper == Looper.getMainLooper()) {
            mMainInstance = choreographer;
        }
        return choreographer;
    }
};

private Choreographer(Looper looper, int vsyncSource) {
    mLooper = looper;
    mHandler = new FrameHandler(looper);
    // 創(chuàng)建FrameDisplayEventReceiver巢掺,用于接收SurfaceFlinger發(fā)給應(yīng)用的Vsync信號
    mDisplayEventReceiver = USE_VSYNC
            ? new FrameDisplayEventReceiver(looper, vsyncSource)
            : null;
    mLastFrameTimeNanos = Long.MIN_VALUE;
    mFrameIntervalNanos = (long)(1000000000 / getRefreshRate());
    // 創(chuàng)建CallbackQueue
    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));
}

mCallbackQueues是一個CallbackQueue數(shù)組句伶,包含四個鏈表

  • CALLBACK_INPUT
    • 輸入回調(diào),當(dāng)接收到Vsync信號時首先運行陆淀,如處理Move事件
  • CALLBACK_ANIMATION
    • 動畫回調(diào)考余,在TRAVERSAL之前運行
  • CALLBACK_TRAVERSAL
    • TRAVERSAL回調(diào),執(zhí)行Measure/Layout/Draw
  • CALLBACK_COMMIT
    • COMMIT回調(diào)轧苫,處理幀繪制完成后的操作楚堤,如應(yīng)用整理內(nèi)存等

FrameDisplayEventReceiver繼承自DisplayEventReceiver,下面分析它構(gòu)造方法

public DisplayEventReceiver(Looper looper, int vsyncSource) {
    if (looper == null) {
        throw new IllegalArgumentException("looper must not be null");
    }
    // Looper關(guān)聯(lián)的MessageQueue
    mMessageQueue = looper.getQueue();
    // Native層的DisplayEventReceiver初始化
    mReceiverPtr = nativeInit(new WeakReference<DisplayEventReceiver>(this), mMessageQueue,
            vsyncSource);
    // CloseGuard用于當(dāng)DisplayEventReceiver被回收時含懊,釋放資源
    mCloseGuard.open("dispose");
}

static jlong nativeInit(JNIEnv* env, jclass clazz, jobject receiverWeak,
        jobject messageQueueObj, jint vsyncSource) {
    // 所在線程的MessageQueue
    sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
    if (messageQueue == NULL) {
        jniThrowRuntimeException(env, "MessageQueue is not initialized.");
        return 0;
    }
    // 創(chuàng)建NativeDisplayEventReceiver身冬,與SurfaceFlinger建立連接
    // 獲取顯示事件socket接收端
    sp<NativeDisplayEventReceiver> receiver = new NativeDisplayEventReceiver(env,
            receiverWeak, messageQueue, vsyncSource);
    // 監(jiān)聽顯示事件socket接收端
    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的構(gòu)造方法

NativeDisplayEventReceiver::NativeDisplayEventReceiver(JNIEnv* env,
        jobject receiverWeak, const sp<MessageQueue>& messageQueue, jint vsyncSource) :
        // 創(chuàng)建DisplayEventDispatcher
        DisplayEventDispatcher(messageQueue->getLooper(),
                static_cast<ISurfaceComposer::VsyncSource>(vsyncSource)),
        // Java層DisplayEventReceiver弱引用的JNI全局引用保存在mReceiverWeakGlobal中
        // 用于后續(xù)向Java層DisplayEventReceiver傳遞顯示事件(Vsync/Hotplug)
        mReceiverWeakGlobal(env->NewGlobalRef(receiverWeak)),
        mMessageQueue(messageQueue) {
    ALOGV("receiver %p ~ Initializing display event receiver.", this);
}

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

DisplayEventReceiver::DisplayEventReceiver(ISurfaceComposer::VsyncSource vsyncSource) {
    // sf是BpSurfaceComposer對象的強(qiáng)指針(對象)
    sp<ISurfaceComposer> sf(ComposerService::getComposerService());
    if (sf != NULL) {
        // mEventConnection為BpDisplayEventConnection的強(qiáng)指針
        // 為客戶端創(chuàng)建顯示事件連接,通過該連接可以請求SurfaceFlinger發(fā)送Vsync以及接收
        // SurfaceFlinger發(fā)送的顯示事件
        mEventConnection = sf->createDisplayEventConnection(vsyncSource);
        if (mEventConnection != NULL) {
            // 創(chuàng)建BitTube
            mDataChannel = std::make_unique<gui::BitTube>();
            // 通過Binder IPC獲取對應(yīng)的Connection的socket接收端
            mEventConnection->stealReceiveChannel(mDataChannel.get());
        }
    }
}

createDisplayEventConnection()是一個Binder IPC岔乔,它的實現(xiàn)在ISurfaceComposer中酥筝。

virtual sp<IDisplayEventConnection> createDisplayEventConnection(VsyncSourcevsyncSource)
{
    Parcel data, reply;
    sp<IDisplayEventConnection> result;
    // 接口描述字符串寫入Parcel中
    int err = data.writeInterfaceToken(
            ISurfaceComposer::getInterfaceDescriptor());
    if (err != NO_ERROR) {
        return result;
    }
    // vsyncSource寫入Parcel中
    data.writeInt32(static_cast<int32_t>(vsyncSource));
    // 請求SurfaceFlinger處理CREATE_DISPLAY_EVENT_CONNECTION
    err = remote()->transact(
            BnSurfaceComposer::CREATE_DISPLAY_EVENT_CONNECTION,
            data, &reply);
    if (err != NO_ERROR) {
        ALOGE("ISurfaceComposer::createDisplayEventConnection: error performing "
                "transaction: %s (%d)", strerror(-err), -err);
        return result;
    }
    // 在應(yīng)用端reply.readStrongBinder()返回BpBinder的強(qiáng)指針
    // interface_case是模板方法
    // result為BpDisplayEventConnection的強(qiáng)指針
    result = interface_cast<IDisplayEventConnection>(reply.readStrongBinder());
    return result;
}

下面看SurfaceFlinger處理CREATE_DISPLAY_EVENT_CONNECTION請求。

status_t BnSurfaceComposer::onTransact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
    switch(code) {
        ......
        case CREATE_DISPLAY_EVENT_CONNECTION: {
            CHECK_INTERFACE(ISurfaceComposer, data, reply);
            // 為客戶端創(chuàng)建連接
            sp<IDisplayEventConnection> connection(createDisplayEventConnection(
                    static_cast<ISurfaceComposer::VsyncSource>(data.readInt32())));
            // connection寫入reply Parcel中
            reply->writeStrongBinder(IInterface::asBinder(connection));
            return NO_ERROR;
        }
        ......
    }
}

sp<IDisplayEventConnection> SurfaceFlinger::createDisplayEventConnection(
        ISurfaceComposer::VsyncSource vsyncSource) {
    if (vsyncSource == eVsyncSourceSurfaceFlinger) {
        return mSFEventThread->createEventConnection();
    } else {
        // 調(diào)用EventThread的createEventConnection()
        return mEventThread->createEventConnection();
    }
}

sp<BnDisplayEventConnection> EventThread::createEventConnection() const {
    // 創(chuàng)建Connection
    return new Connection(const_cast<EventThread*>(this));
}

Connection是一個Binder服務(wù)類雏门,繼承自BnDisplayEventConnection嘿歌,它的作用

  • 處理客戶端應(yīng)用的Vsync請求
  • 向客戶端應(yīng)用發(fā)送顯示事件(Vsync/Hotplug)

下面看Connection的構(gòu)造方法

EventThread::Connection::Connection(EventThread* eventThread)
      // 創(chuàng)建BitTube
      : count(-1), mEventThread(eventThread), mChannel(gui::BitTube::DefaultSize) {}

BitTube::BitTube(size_t bufsize) {
    // 創(chuàng)建socket pair,用于發(fā)送顯示事件
    init(bufsize, bufsize);
}

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;
        // 設(shè)置socket buffer
        setsockopt(sockets[0], SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf));
        setsockopt(sockets[1], SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf));
        // since 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);
        // socket[0]用于接收端茁影,最終通過Binder IPC返回給客戶端應(yīng)用
        mReceiveFd.reset(sockets[0]);
        // socket[1]用于發(fā)送端
        mSendFd.reset(sockets[1]);
    } else {
        mReceiveFd.reset();
        ALOGE("BitTube: pipe creation failed (%s)", strerror(errno));
    }
}

BitTube的作用主要有

  • 封裝用于顯示事件的socket通信
  • 跨進(jìn)程傳遞socket文件描述符

回到createEventConnection()方法中宙帝,由于返回Connection的強(qiáng)指針,在sp的構(gòu)造函數(shù)中會增加強(qiáng)引用計數(shù)從而調(diào)用ConnectiononFirstRef()方法募闲。

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

status_t EventThread::registerDisplayEventConnection(
        const sp<EventThread::Connection>& connection) {
    std::lock_guard<std::mutex> lock(mMutex);
    // Connection添加到mDisplayEventConnections中
    mDisplayEventConnections.add(connection);
    mCondition.notify_all();
    return NO_ERROR;
}

ConnectionEventThread采用觀察者模式步脓,當(dāng)有顯示事件發(fā)生時,EventThreadConnection傳遞事件浩螺。至此靴患,createDisplayEventConnection()的實現(xiàn)就分析完了,下面看stealReceiveChannel()的實現(xiàn)

status_t stealReceiveChannel(gui::BitTube* outChannel) override {
    // callRemote是一個模板方法年扩,用于實現(xiàn)同步Binder IPC
    return callRemote<decltype(
            &IDisplayEventConnection::stealReceiveChannel)>(Tag::STEAL_RECEIVE_CHANNEL,
                                                            outChannel);
}

下面看Connection處理STEAL_RECEIVE_CHANNEL請求

status_t BnDisplayEventConnection::onTransact(uint32_t code, const Parcel& data, Parcel* reply,
                                              uint32_t flags) {
    if (code < IBinder::FIRST_CALL_TRANSACTION || code > static_cast<uint32_t>(Tag::LAST)) {
        return BBinder::onTransact(code, data, reply, flags);
    }
    auto tag = static_cast<Tag>(code);
    switch (tag) {
        case Tag::STEAL_RECEIVE_CHANNEL:
            // 調(diào)用stealReceiveChannel處理請求
            // 最終通過BitTube(outChannel)的writeToParcel將socket接收端文件描述符寫入reply
            return callLocal(data, reply, &IDisplayEventConnection::stealReceiveChannel);
        ......
    }
}

status_t EventThread::Connection::stealReceiveChannel(gui::BitTube* outChannel) {
    // 設(shè)置socket接收端文件描述符
    outChannel->setReceiveFd(mChannel.moveReceiveFd());
    return NO_ERROR;
}

最終蚁廓,客戶端應(yīng)用通過BitTubereadFromParcel()獲取來自SurfaceFlinger的socket文件描述符。這樣客戶端就可以接收SurfaceFlinger發(fā)送的顯示事件了厨幻∠嗲叮回到nativeInit()中,繼續(xù)看監(jiān)聽socket接收端文件描述符的過程况脆。

status_t DisplayEventDispatcher::initialize() {
    status_t result = mReceiver.initCheck();
    if (result) {
        ALOGW("Failed to initialize display event receiver, status=%d", result);
        return result;
    }
    // Looper監(jiān)聽socket文件描述符
    int rc = mLooper->addFd(mReceiver.getFd(), 0, Looper::EVENT_INPUT,
            this, NULL);
    if (rc < 0) {
        return UNKNOWN_ERROR;
    }
    return OK;
}

DisplayEventDispatcher繼承自LooperCallback饭宾,當(dāng)有顯示事件到來時,Looper關(guān)聯(lián)的線程將調(diào)用DisplayEventDispatcherhandleEvent()處理事件格了。這樣Android應(yīng)用與SurfaceFlinger就建立了連接看铆,可以接收SurfaceFlinger發(fā)送的顯示事件了。

為了后續(xù)分析盛末,下面繼續(xù)分析ViewRootImplsetView()

public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView {
    synchronized (this) {
        if (mView == null) {
            mView = view;
            mAttachInfo.mDisplayState = mDisplay.getState();
            mDisplayManager.registerDisplayListener(mDisplayListener, mHandler);
            mViewLayoutDirectionInitial = mView.getRawLayoutDirection();
            mFallbackEventHandler.setView(view);
            mWindowAttributes.copyFrom(attrs);
            if (mWindowAttributes.packageName == null) {
                mWindowAttributes.packageName = mBasePackageName;
            }
            attrs = mWindowAttributes;
            setTag();
            ......
            // If the application owns the surface, don't enable hardware acceleration
            // 如果應(yīng)用有自己的Surface弹惦,不使能硬件加速
            if (mSurfaceHolder == null) {
                // While this is supposed to enable only, it can effectively disable
                // the acceleration too.
                // 使能硬件加速否淤,也可以禁止
                enableHardwareAcceleration(attrs);
                final boolean useMTRenderer = MT_RENDERER_AVAILABLE
                        && mAttachInfo.mThreadedRenderer != null;
                if (mUseMTRenderer != useMTRenderer) {
                    // Shouldn't be resizing, as it's done only in window setup,
                    // but end just in case.
                    endDragResizing();
                    mUseMTRenderer = useMTRenderer;
                }
            }
            ......
            // 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.
            // 調(diào)度首次layout, 請求SurfaceFlinger發(fā)送Vsync
            requestLayout();
            ......
            try {
                mOrigWindowType = mWindowAttributes.type;
                mAttachInfo.mRecomputeGlobalAttributes = true;
                collectViewAttributes();
                // 窗口注冊到WindowManagerService
                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();
                }
            }
            ......
        }
    }
}                                

下面重點分析上述方法中的以下三個過程

  • 使能硬件加速的過程
  • 調(diào)度首次layout的過程
  • 窗口注冊到WindowManagerService的過程

使能硬件加速的過程

下面從enableHardwareAcceleration()開始分析棠隐。

private void enableHardwareAcceleration(WindowManager.LayoutParams attrs) {
    mAttachInfo.mHardwareAccelerated = false;
    mAttachInfo.mHardwareAccelerationRequested = false;
    // Don't enable hardware acceleration when the application is in compatibility mode
    if (mTranslator != null) return;
    // Try to enable hardware acceleration if requested
    // 默認(rèn)hardwareAccelerated為true
    // 在低端設(shè)備上隐解,Persistent進(jìn)程(包括system進(jìn)程)不應(yīng)該使用hardwareAccelerated岩臣,因為hardwareAccelerated消耗更多的資源叼耙,比如內(nèi)存
    final boolean hardwareAccelerated =
            (attrs.flags & WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED) != 0;
    if (hardwareAccelerated) {
        if (!ThreadedRenderer.isAvailable()) {
            return;
        }
        ......
        // 對于startingWindow端铛,設(shè)置窗口的FLAG_HARDWARE_ACCELERATED及PRIVATE_FLAG_FAKE_HARDWARE_ACCELERATED使得繪制與應(yīng)用窗口繪制相似(并非真正的hardwareAccelerated)
        final boolean fakeHwAccelerated = (attrs.privateFlags &
                WindowManager.LayoutParams.PRIVATE_FLAG_FAKE_HARDWARE_ACCELERATED) != 0;
        // 用于在system進(jìn)程中骨稿,某些UI繪制強(qiáng)制使用hardwareAccelerated
        final boolean forceHwAccelerated = (attrs.privateFlags &
                WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_HARDWARE_ACCELERATED) != 0;
        if (fakeHwAccelerated) {
            // This is exclusively for the preview windows the window manager
            // shows for launching applications, so they will look more like
            // the app being launched.
            mAttachInfo.mHardwareAccelerationRequested = true;
        } else if (!ThreadedRenderer.sRendererDisabled
                || (ThreadedRenderer.sSystemRendererDisabled && forceHwAccelerated)) {
            // 使能硬件加速
            if (mAttachInfo.mThreadedRenderer != null) {
                mAttachInfo.mThreadedRenderer.destroy();
            }
            final Rect insets = attrs.surfaceInsets;
            final boolean hasSurfaceInsets = insets.left != 0 || insets.right != 0
                    || insets.top != 0 || insets.bottom != 0;
            // 是否透明
            final boolean translucent = attrs.format != PixelFormat.OPAQUE || hasSurfaceInsets;
            final boolean wideGamut =
                    mContext.getResources().getConfiguration().isScreenWideColorGamut()
                    && attrs.getColorMode() == ActivityInfo.COLOR_MODE_WIDE_COLOR_GAMUT;
            // 創(chuàng)建ThreadedRenderer
            mAttachInfo.mThreadedRenderer = ThreadedRenderer.create(mContext, translucent,
                    attrs.getTitle().toString());
            mAttachInfo.mThreadedRenderer.setWideGamut(wideGamut);
            if (mAttachInfo.mThreadedRenderer != null) {
                mAttachInfo.mHardwareAccelerated =
                        mAttachInfo.mHardwareAccelerationRequested = true;
            }
        }
    }
}
  • ThreaderedRenderer用于將渲染工作委托給RenderThread

下面看ThreaderedRenderercreate()方法

public static ThreadedRenderer create(Context context, boolean translucent, Stringname) {
    ThreadedRenderer renderer = null;
    if (isAvailable()) {
        // 檢查是否支持Threaded rendering
        // 舊版本的模擬器可能不支持
        renderer = new ThreadedRenderer(context, translucent, name);
    }
    return renderer;
}

ThreadedRenderer(Context context, boolean translucent, String name) {
    final TypedArray a = context.obtainStyledAttributes(null, R.styleable.Lighting, 0, 0);
    mLightY = a.getDimension(R.styleable.Lighting_lightY, 0);
    mLightZ = a.getDimension(R.styleable.Lighting_lightZ, 0);
    mLightRadius = a.getDimension(R.styleable.Lighting_lightRadius, 0);
    mAmbientShadowAlpha =
            (int) (255 * a.getFloat(R.styleable.Lighting_ambientShadowAlpha, 0) + 0.5f);
    mSpotShadowAlpha = (int) (255 * a.getFloat(R.styleable.Lighting_spotShadowAlpha, 0) + 0.5f);
    a.recycle();
    // 創(chuàng)建Native RootRenderNode對象丑慎,rootNodePtr為對象的地址
    long rootNodePtr = nCreateRootRenderNode();
    // 產(chǎn)生一個Java RenderNode關(guān)聯(lián)Native RenderNode
    mRootNode = RenderNode.adopt(rootNodePtr);
    mRootNode.setClipToBounds(false);
    mIsOpaque = !translucent;
    // 創(chuàng)建RenderProxy及RenderThread
    mNativeProxy = nCreateProxy(translucent, rootNodePtr);
    nSetName(mNativeProxy, name);
    // 1) 設(shè)置RenderThread的調(diào)度信息
    // 2) 請求系統(tǒng)GraphicsStatsService創(chuàng)建匿名共享內(nèi)存弧烤,用于存儲應(yīng)用渲染信息(dumpsys gfxinfo)
    ProcessInitializer.sInstance.init(context, mNativeProxy);
    // 加載渲染所需的系統(tǒng)屬性
    loadSystemProperties();
}
  • RenderNode
    • 存儲記錄的畫布命令熊榛,以及View/ViewGroup的顯示屬性
  • RenderProxy
    • 創(chuàng)建以及管理RenderThread中的CanvasContext
  • RenderThread
    • 真正的渲染線程
      下面首先看RootRenderNode的創(chuàng)建疯攒,然后分析RenderProxy及RenderThread会喝。
static jlong android_view_ThreadedRenderer_createRootRenderNode(JNIEnv* env, jobject clazz) {
    // 創(chuàng)建RootRenderNode
    RootRenderNode* node = new RootRenderNode(env);
    node->incStrong(0);
    node->setName("RootRenderNode");
    return reinterpret_cast<jlong>(node);
}

explicit RootRenderNode(JNIEnv* env) : RenderNode() {
    // 獲取調(diào)用線程關(guān)聯(lián)的Looper
    mLooper = Looper::getForThread();
    LOG_ALWAYS_FATAL_IF(!mLooper.get(),
            "Must create RootRenderNode on a thread with a looper!");
    // 返回JavaVM
    env->GetJavaVM(&mVm);
}

這里只是簡單的創(chuàng)建RootRenderNode末秃,下面看RenderProxy及RenderThread的創(chuàng)建概页。

static jlong android_view_ThreadedRenderer_createProxy(JNIEnv* env, jobject clazz,
        jboolean translucent, jlong rootRenderNodePtr) {
    RootRenderNode* rootRenderNode = reinterpret_cast<RootRenderNode*>(rootRenderNodePtr);
    // 創(chuàng)建ContextFactoryImpl
    ContextFactoryImpl factory(rootRenderNode);
    // 創(chuàng)建RenderProxy
    return (jlong) new RenderProxy(translucent, rootRenderNode, &factory);
}

RenderProxy::RenderProxy(bool translucent, RenderNode* rootRenderNode,
                         IContextFactory* contextFactory)
        // 創(chuàng)建啟動RenderThread線程
        : mRenderThread(RenderThread::getInstance()), mContext(nullptr) {
    // 匿名函數(shù)創(chuàng)建CanvasContext
    mContext = mRenderThread.queue().runSync([&]() -> CanvasContext* {
        return CanvasContext::create(mRenderThread, translucent, rootRenderNode, contextFactory);
    });
    設(shè)置DrawFrameTask關(guān)聯(lián)的RenderThread、CanvasContext练慕、RootRenderNode
    mDrawFrameTask.setContext(&mRenderThread, mContext, rootRenderNode);
}

RenderThread& RenderThread::getInstance() {
    // This is a pointer because otherwise __cxa_finalize
    // will try to delete it like a Good Citizen but that causes us to crash
    // because we don't want to delete the RenderThread normally.
    static RenderThread* sInstance = new RenderThread();
    gHasRenderThreadInstance = true;
    return *sInstance;
}

RenderThread::RenderThread()
        : ThreadBase()
        , mVsyncSource(nullptr)
        , mVsyncRequested(false)
        , mFrameCallbackTaskPending(false)
        , mRenderState(nullptr)
        , mEglManager(nullptr)
        , mVkManager(nullptr) {
    Properties::load();
    // 啟動線程惰匙,最終執(zhí)行RenderThread的threadLoop方法
    start("RenderThread");
}

bool RenderThread::threadLoop() {
    // 設(shè)置RenderThread的優(yōu)先級
    setpriority(PRIO_PROCESS, 0, PRIORITY_DISPLAY);
    if (gOnStartHook) {
        gOnStartHook();
    }
    // 與SurfaceFlinger建立連接
    // 設(shè)置EglManager、RenderState铃将、VulkanManager等
    initThreadLocals();

    while (true) {
        // 等待工作
        waitForWork();
        // 處理工作項
        processQueue();

        if (mPendingRegistrationFrameCallbacks.size() && !mFrameCallbackTaskPending) {
            drainDisplayEventQueue();
            mFrameCallbacks.insert(mPendingRegistrationFrameCallbacks.begin(),
                                   mPendingRegistrationFrameCallbacks.end());
            mPendingRegistrationFrameCallbacks.clear();
            requestVsync();
        }

        if (!mFrameCallbackTaskPending && !mVsyncRequested && mFrameCallbacks.size()) {
            // TODO: Clean this up. This is working around an issue where a combination
            // of bad timing and slow drawing can result in dropping a stale vsync
            // on the floor (correct!) but fails to schedule to listen for the
            // next vsync (oops), so none of the callbacks are run.
            requestVsync();
        }
    }

    return false;
}

RenderThread啟動后项鬼,RenderProxy向RenderThread發(fā)送創(chuàng)建CanvasContext的同步請求。下面看CanvasContext的創(chuàng)建劲阎。

CanvasContext* CanvasContext::create(RenderThread& thread, bool translucent,
                                     RenderNode* rootRenderNode, IContextFactory* contextFactory) {
    // 獲取RenderPipeline類型绘盟,默認(rèn)是SkiaGL
    auto renderType = Properties::getRenderPipelineType();

    switch (renderType) {
        case RenderPipelineType::OpenGL:
            return new CanvasContext(thread, translucent, rootRenderNode, contextFactory,
                                     std::make_unique<OpenGLPipeline>(thread));
        case RenderPipelineType::SkiaGL:
            // 根據(jù)renderType創(chuàng)建CanvasContext
            return new CanvasContext(thread, translucent, rootRenderNode, contextFactory,
                                     std::make_unique<skiapipeline::SkiaOpenGLPipeline>(thread));
        case RenderPipelineType::SkiaVulkan:
            return new CanvasContext(thread, translucent, rootRenderNode, contextFactory,
                                     std::make_unique<skiapipeline::SkiaVulkanPipeline>(thread));
        default:
            LOG_ALWAYS_FATAL("canvas context type %d not supported", (int32_t)renderType);
            break;
    }
    return nullptr;
}

調(diào)度首次layout的過程

下面從requestLayout()開始分析。

public void requestLayout() {
    if (!mHandlingLayoutInLayoutRequest) {
        checkThread();
        mLayoutRequested = true;
        scheduleTraversals();
    }
}

void scheduleTraversals() {
    if (!mTraversalScheduled) {
        mTraversalScheduled = true;
        // 向Looper關(guān)聯(lián)的消息隊列中投遞SyncBarrier
        // 下一次執(zhí)行performTraversal時移除SyncBarrier
        mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
        // 添加CALLBACK_TRAVERSAL回調(diào),當(dāng)下一幀(Vsync)到來時執(zhí)行繪制
        mChoreographer.postCallback(
                Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
        if (!mUnbufferedInputDispatch) {
            scheduleConsumeBatchedInput();
        }
        // 通知ThreadedRenderer下一幀很快到來
        notifyRendererOfFramePending();
        pokeDrawLockIfNeeded();
    }
}

關(guān)于synchronization barrier(target為null的特殊消息), 一般的龄毡,消息隊列中的消息為同步消息吠卷,按照時間先后進(jìn)行處理。當(dāng)synchronization barrier進(jìn)入消息隊列中稚虎,隊列中的同步消息被掛起(異步消息可以處理)撤嫩,直到synchronization barrier從消息隊列中移除。盡管postAtFrontOfQueue()可以使同步消息不被掛起蠢终,請不要濫用。

下面看ChoreographerpostCallback()的實現(xiàn)茴她。

public void postCallback(int callbackType, Runnable action, Object token) {
    postCallbackDelayed(callbackType, action, token, 0);
}

public void postCallbackDelayed(int callbackType,
        Runnable action, Object token, long delayMillis) {
    ......
    postCallbackDelayedInternal(callbackType, action, token, delayMillis);
}

private void postCallbackDelayedInternal(int callbackType,
        Object action, Object token, long delayMillis) {
    ......
    synchronized (mLock) {
        final long now = SystemClock.uptimeMillis();
        final long dueTime = now + delayMillis;
        // 添加到CALLBACK_TRAVERSAL類型的CallbackQueue中
        mCallbackQueues[callbackType].addCallbackLocked(dueTime, action, token);
        if (dueTime <= now) {
            // 請求Vsync信號
            scheduleFrameLocked(now);
        } else {
            ......
        }
    }
}

下面看scheduleFrameLocked()的實現(xiàn)

private void 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()) {
                // 立即請求Vsync
                scheduleVsyncLocked();
            } else {
                Message msg = mHandler.obtainMessage(MSG_DO_SCHEDULE_VSYNC);
                msg.setAsynchronous(true);
                mHandler.sendMessageAtFrontOfQueue(msg);
            }
        } else {
            ......
        }
    }
}

private void scheduleVsyncLocked() {
    // 調(diào)用FrameDisplayEventReceiver的scheduleVsync()
    mDisplayEventReceiver.scheduleVsync();
}

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 {
        // 當(dāng)下一幀到來時請求SurfaceFlinger發(fā)送Vsync
        nativeScheduleVsync(mReceiverPtr);
    }
}

static void nativeScheduleVsync(JNIEnv* env, jclass clazz, jlong receiverPtr) {
    sp<NativeDisplayEventReceiver> receiver =
            reinterpret_cast<NativeDisplayEventReceiver*>(receiverPtr);
    // 調(diào)用NativeDisplayEventReceiver的scheduleVsync()
    status_t status = receiver->scheduleVsync();
    ......
}

NativeDisplayEventReceiver繼承自DisplayEventDispatcher寻拂,下面scheduleVsync()的實現(xiàn)

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;
        // 如果有待處理的事件(Vsync/Hotplug),丟棄
        if (processPendingEvents(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount)) {
            ALOGE("dispatcher %p ~ last event processed while scheduling was for %" PRId64 "",
                    this, ns2ms(static_cast<nsecs_t>(vsyncTimestamp)));
        }
        // 調(diào)用DisplayEventReceiver的requestNextVsync()丈牢,請求SurfaceFlinger發(fā)送Vsync
        status_t status = mReceiver.requestNextVsync();
        if (status) {
            ALOGW("Failed to request next vsync, status=%d", status);
            return status;
        }

        mWaitingForVsync = true;
    }
    return OK;
}

status_t DisplayEventReceiver::requestNextVsync() {
    if (mEventConnection != NULL) {
        // mEventConnection是BpDisplayEventConnection的強(qiáng)指針
        mEventConnection->requestNextVsync();
        return NO_ERROR;
    }
    return NO_INIT;
}

requestNextVsync()是一個異步Binder IPC祭钉,它的實現(xiàn)在IDisplayEventConnection中,下面直接看Binder服務(wù)端Connection處理REQUEST_NEXT_VSYNC請求己沛。

void EventThread::Connection::requestNextVsync() {
    // 調(diào)用EventThread的requestNextVsync處理客戶端Vsync請求
    mEventThread->requestNextVsync(this);
}

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

    ......
    // 修改連接狀態(tài)
    if (connection->count < 0) {
        connection->count = 0;
        mCondition.notify_all();
    }
}

客戶端請求Vsync的過程相對簡單慌核,主要是修改Connection的狀態(tài)。當(dāng)EventThread收到Vsync時申尼,根據(jù)Connection的狀態(tài)決定是否向Connection發(fā)送Vsync垮卓。

使用dumpsys SurfaceFlinger命令可以查看所有Connection的狀態(tài)
****chn:/ $ dumpsys SurfaceFlinger
......
VSYNC state: enabled
  soft-vsync: disabled
  numListeners=43,
  events-delivered: 11406
    0x7b3a052300: count=-1
    0x7b3a052360: count=-1
    0x7b3a0523c0: count=-1
    0x7b3a052420: count=-1
    0x7b3a0524e0: count=-1
    0x7b3a052960: count=-1
    0x7b3a0529c0: count=-1
    ......
    0x7b3abfe200: count=1
    ......

其中,numListeners表示連接數(shù)量师幕,count的值表示狀態(tài)
  • count >= 1
    • 連續(xù)的Vsync請求
  • count = 0
    • 單次Vsync請求(還沒有收到Vsync)
  • count = -1
    • 單次Vsync請求(已經(jīng)收到Vsync)或者不請求Vsync

窗口注冊到WindowManagerService的過程

下面從addToDisplay()開始分析粟按,addToDisplay()是一個Binder IPC,對應(yīng)的服務(wù)端的實現(xiàn)在Session中霹粥。

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) {
    // 調(diào)用WindowManagerService的addWindow
    return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId, outFrame,
            outContentInsets, outStableInsets, outOutsets, outDisplayCutout, outInputChannel);
}

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) {
    // client為IWindow.Stub.Proxy對象
    ......
    boolean reportNewConfig = false;
    WindowState parentWindow = null;
    long origId;
    final int callingUid = Binder.getCallingUid();
    final int type = attrs.type; 
    synchronized(mWindowMap) {
        if (!mDisplayReady) {
            throw new IllegalStateException("Display has not been initialialized");
        }
        // DisplayContent用于記錄特定屏幕的WindowStates以及相關(guān)的內(nèi)容
        final DisplayContent displayContent = getDisplayContentOrCreate(displayId);
        ......
        // 檢查應(yīng)用是否有權(quán)限向特定屏幕添加窗口
        if (!displayContent.hasAccess(session.mUid)
                && !mDisplayManagerInternal.isUidPresentOnDisplay(session.mUid, displayId)) {
            Slog.w(TAG_WM, "Attempted to add window to a display for which the application "
                    + "does not have access: " + displayId + ".  Aborting.");
            return WindowManagerGlobal.ADD_INVALID_DISPLAY;
        }
        ......
        // 檢查窗口是否已經(jīng)添加
        // mWindowMap為IWindow IBinder(BinderProxy)到WindowState的映射
        if (mWindowMap.containsKey(client.asBinder())) {
            Slog.w(TAG_WM, "Window " + client + " is already added");
            return WindowManagerGlobal.ADD_DUPLICATE_ADD;
        }
        ......
        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.
        // 對于Activity窗口灭将,根據(jù)token(IApplicationToken.Stub)查找對應(yīng)的AppWindowToken
        // AppWindowToken是在之前Activity啟動時創(chuàng)建
        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;
        ......
        // 創(chuàng)建WindowState用于描述一個窗口
        final WindowState win = new WindowState(this, session, client, token, parentWindow,
                appOp[0], seq, attrs, viewVisibility, session.mUid,
                session.mCanAddInternalSystemWindow);
        ......
        // 根據(jù)窗口類型調(diào)整布局參數(shù)
        mPolicy.adjustWindowParamsLw(win, win.mAttrs, hasStatusBarServicePermission);
        win.setShowToOwnerOnlyLocked(mPolicy.checkShowToOwnerOnly(attrs));
        // 窗口添加到系統(tǒng)前的檢查
        res = mPolicy.prepareAddWindowLw(win, attrs);
        ......
        // 創(chuàng)建SurfaceSession,添加Session到WindowManagerService
        win.attach();
        // WindowState添加到mWindowMap
        mWindowMap.put(client.asBinder(), win);
        win.initAppOpsState(); 
        ......
        // 窗口WindowState添加到系統(tǒng)
        win.mToken.addWindow(win); 
        ......
        // 這里WindowState的Parent為AppWindowToken
        win.getParent().assignChildLayers();
    }                               
}

下面重點分析WindowStateattach()方法

void attach() {
    if (localLOGV) Slog.v(TAG, "Attaching " + this + " token=" + mToken);
    // 調(diào)用Session的windowAddedLocked
    mSession.windowAddedLocked(mAttrs.packageName);
}

void windowAddedLocked(String packageName) {
    mPackageName = packageName;
    mRelayoutTag = "relayoutWindow: " + mPackageName;
    if (mSurfaceSession == null) {
        if (WindowManagerService.localLOGV) Slog.v(
            TAG_WM, "First window added to " + this + ", creating SurfaceSession");
        // SurfaceSession代表一個到SurfaceFlinger的連接
        // 可以有一個或多個參與合成的Surface
        mSurfaceSession = new SurfaceSession();
        if (SHOW_TRANSACTIONS) Slog.i(
                TAG_WM, "  NEW SURFACE SESSION " + mSurfaceSession);
        // Session添加到WindowManagerService的mSessions中
        mService.mSessions.add(this);
        if (mLastReportedAnimatorScale != mService.getCurrentAnimatorScale()) {
            mService.dispatchNewAnimatorScaleLocked(this);
        }
    }
    mNumWindow++;
}

下面看SurfaceSession的構(gòu)造方法。

public SurfaceSession() {
    mNativeClient = nativeCreate();
}

static jlong nativeCreate(JNIEnv* env, jclass clazz) {
    // 創(chuàng)建SurfaceComposerClient
    SurfaceComposerClient* client = new SurfaceComposerClient();
    // SurfaceComposerClient繼承自RefBase,增加強(qiáng)引用計數(shù)后控,會調(diào)用onFirstRef
    client->incStrong((void*)nativeCreate);
    return reinterpret_cast<jlong>(client);
}

void SurfaceComposerClient::onFirstRef() {
    sp<ISurfaceComposer> sf(ComposerService::getComposerService());
    if (sf != 0 && mStatus == NO_INIT) {
        // 這里rootProducer為nullptr
        auto rootProducer = mParent.promote();
        sp<ISurfaceComposerClient> conn;
        // 請求SurfaceFlinger為客戶端創(chuàng)建連接
        // conn為BpSurfaceComposerClient對象的智能指針
        conn = (rootProducer != nullptr) ? sf->createScopedConnection(rootProducer) :
                sf->createConnection();
        if (conn != 0) {
            mClient = conn;
            mStatus = NO_ERROR;
        }
    }
}

createConnection()是一個Binder IPC庙曙,下面直接看SurfaceFlinger處理CREATE_CONNECTION請求。

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

Client為參與合成的客戶端在SurfaceFlinger側(cè)的代表浩淘,是一個Binder服務(wù)對象,通過Binder IPC傳遞后捌朴,在客戶端得到BpSurfaceComposerClient對象。

小結(jié)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末馋袜,一起剝皮案震驚了整個濱河市男旗,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌欣鳖,老刑警劉巖察皇,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡什荣,警方通過查閱死者的電腦和手機(jī)矾缓,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來稻爬,“玉大人嗜闻,你說我怎么就攤上這事∥Τ” “怎么了琉雳?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長友瘤。 經(jīng)常有香客問我翠肘,道長,這世上最難降的妖魔是什么辫秧? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任束倍,我火速辦了婚禮,結(jié)果婚禮上盟戏,老公的妹妹穿的比我還像新娘绪妹。我一直安慰自己,他們只是感情好柿究,可當(dāng)我...
    茶點故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布邮旷。 她就那樣靜靜地躺著,像睡著了一般笛求。 火紅的嫁衣襯著肌膚如雪廊移。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天探入,我揣著相機(jī)與錄音狡孔,去河邊找鬼。 笑死蜂嗽,一個胖子當(dāng)著我的面吹牛苗膝,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播植旧,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼辱揭,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了病附?” 一聲冷哼從身側(cè)響起问窃,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎完沪,沒想到半個月后域庇,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體嵌戈,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年听皿,在試婚紗的時候發(fā)現(xiàn)自己被綠了熟呛。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡尉姨,死狀恐怖庵朝,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情又厉,我是刑警寧澤九府,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站覆致,受9級特大地震影響昔逗,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜篷朵,卻給世界環(huán)境...
    茶點故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望婆排。 院中可真熱鬧声旺,春花似錦、人聲如沸段只。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽赞枕。三九已至澈缺,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間炕婶,已是汗流浹背姐赡。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留柠掂,地道東北人项滑。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像涯贞,于是被迫代替她去往敵國和親枪狂。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,916評論 2 344