WMS-1.addWindow

514 阅读8分钟

主要内容

  1. WMS何时启动的,与ATMS,RootWindowContainer如何建立联系 startOtherServices
  2. DecorView--> Window performResumeActivity
    • 在handleResumeActivity-->performResumeActivity(回调onresume), 然后执行wm.addView(decor, l);
  3. ViewRootImpl构造函数,setView方法 :
    • requestLayout()--在添加窗口前处理第一次layout,注册vsync信号监听器,准备进行layout;mWindowSession.addToDisplayAsUser通知WMS添加窗口
  4. addWindow时,创建WindowToken,将该对象添加到DisplayContent中 关键layerTree
    • mImeWindowsContainers、mOverlayContainers和mDisplayAreaPolicy将作为WindowToken的父容器对其进行管理
    • 得到WindowToken对象后,接下来将创建WindowState对象
      • 一个WindowState代表了一个具体的Window,每添加一个Window,都会创建对应的WindowState;
      • 计算BaseLayer和SubLayer值,并将sub-window添加到parent-window中 parentWindow.addChild(this, sWindowSubLayerComparator);
      • 创建WindowState过程中,对WindState类中的许多属性进行了初始化操作,其中还创建了两个对象——WindowStateAnimator对象和InputWindowHandle对象;
      • WindowStateAnimator对象用来为WindowState对象进行动画和Surface的转变操作,绘制过程中,动画的状态和Surface状态都会由该对象来进行记录;
      • InputWindowHandle对象则用于input事件的分发,通过内部的IBinder类型的token,将InputChannel和WindowState进行关联.
  5. 通过win.attach方法与SF建立连接
    • mWindowSession.addToDisplayAsUser先于requestLayout执行 requestLayout中需要与SF通信获取Surface
  6. 将WindowState对象添加到WindowToken中
    • WindowToken将作为WindowState的父容器 win.mToken.addWindow(win); addChild(win, mWindowComparator);

1. WMS启动

image.png

  • mRoot:系统中所有display的所有窗口容器的根节点。它的孩子是DisplayContent,是持有所有的DisplayContent
  • LocalServices会保存一个WMS内部实现的LocalService,该类集成自WindowManagerInternal,外部可以通过LocalServices.getService(Win...)获取该类
  • WindowManagerInternal是一个抽象类,WMS内的LocalService实现该类
  • LocalService是各个服务的内部类 各自继承Internal

2. 如何从DecorView-->Window

image.png

  • token的传递【1】ss进程为app创建activityrecord实例,在ar构造方法中创建token,在WindowToken的构造方法里会将创建的ActivityRecord添加到DisplayContent中(dc.addWindowToken)的mTokenMap去,这个Map的key就是创建的Token(后续会传递给App,App在添加窗口的时候WMS会检查这个Token是否合法)
    • realStartActivityLocked--创建clientTransactio.obtain(r.token),经Binder IPC传递到App端创建ActivityClientRecord(token)--->handleLaunchActivity(ActivityClientRecord r)--->performLaunchActivity()在Activity.attch(r.token)方法中创建一个phoneWindow,将token传递给WindowManager(setWindowManager),这样从ss进程创建的ActivityRecord.Token实例就已经通过Binder传递在App进程中保存了,分别存于Activity的mToken和Window的mAppToken中
  • 在app端的onCreate()方法中会调用setContentView(xml)创建DecorView,把布局加入Content里面,这时DecorView还不可见
  • performLaunchActivity()执行后,执行handleResumeActivity()通过performResumeActivity()处理Activity的onstart,onResume生命周期

2.1 setView()

  • ViewRootImpl构造函数
public ViewRootImpl(Context context, Display display, IWindowSession session,
          boolean useSfChoreographer) {
          mWindowSession = session;    //与WMS进行通信的binder
          mThread = Thread.currentThread();//当前UI线程
          mWindow = new W(this); //传递给WMS,用来和app通信
          mChoreographer = useSfChoreographer
              ? Choreographer.getSfInstance() : Choreographer.getInstance();// 编舞者,屏幕刷新机制,vsync信号

}
  • setView函数
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView,
            int userId) {
        synchronized (this) {
            if (mView == null) {
                mView = view;   //创建好的DecorView             
                ......
              
                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.
                // 在添加窗口前处理第一次layout,注册vsync信号监听器,准备进行layout
                requestLayout();
                .......

                try {
                    .......
                    // 通知WMS添加窗口
                    res = mWindowSession.addToDisplayAsUser(mWindow, mSeq, mWindowAttributes,
                            getHostVisibility(), mDisplay.getDisplayId(), userId, mTmpFrame,
                            mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
                            mAttachInfo.mDisplayCutout, inputChannel,
                            mTempInsets, mTempControls);
                    setFrame(mTmpFrame);
                } 
                ......

                // insets处理
                if (mTranslator != null) {
                    mTranslator.translateRectInScreenToAppWindow(mAttachInfo.mContentInsets);
                }
                mPendingDisplayCutout.set(mAttachInfo.mDisplayCutout);
                mAttachInfo.mAlwaysConsumeSystemBars =
                        (res & WindowManagerGlobal.ADD_FLAG_ALWAYS_CONSUME_SYSTEM_BARS) != 0;
                mPendingAlwaysConsumeSystemBars = mAttachInfo.mAlwaysConsumeSystemBars;
                mInsetsController.onStateChanged(mTempInsets);
                mInsetsController.onControlsChanged(mTempControls);
                
                .......

            }
        }
    }

分为两部分:

  • 通知WMS添加窗口 mWindowSession.addToDisplayAsUser 涉及跨进程调用,调用WMS.addWindow方法

2.2 addWindow()添加窗口

public int addWindow(Session session, IWindow client, int seq,
            LayoutParams attrs, int viewVisibility, int displayId, Rect outFrame,
            Rect outContentInsets, Rect outStableInsets,
            DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel,
            InsetsState outInsetsState, InsetsSourceControl[] outActiveControls,
            int requestUserId) {
        	......
	// 获取Window type
    final int type = attrs.type;

    synchronized (mGlobalLock) {
        ......
        ActivityRecord activity = null;
        // 对于type为SUB_WINDOW的窗口,判断是否存在父窗口
        final boolean hasParent = parentWindow != null;
        // 根据attr.token获取WindowToken对象
        WindowToken token = displayContent.getWindowToken(
                hasParent ? parentWindow.mAttrs.token : attrs.token);

        final int rootType = hasParent ? parentWindow.mAttrs.type : type;
        // 如果不存在WindowToken,创建新的WindowToken
        if (token == null) {
            final IBinder binder = attrs.token != null ? attrs.token : client.asBinder();
            token = new WindowToken(this, binder, type, false, displayContent,
                    session.mCanAddInternalSystemWindow, isRoundedCornerOverlay);
        // 如果是Application类型的窗口,则该WindowToken向下转型为ActivityRecord
        } else if (rootType >= FIRST_APPLICATION_WINDOW
                && rootType <= LAST_APPLICATION_WINDOW) {
            activity = token.asActivityRecord();
        .........
        } 
        
        //创建windowState对象,计算baseLayer和SubLayer,根据type判断事都是输入法窗口和壁纸窗口,锁屏时是否可见
        final WindowState win = new WindowState(this, session, client, token, parentWindow,
                appOp[0], seq, attrs, viewVisibility, session.mUid, userId,
                session.mCanAddInternalSystemWindow);
        // 调整win.mAttrs属性
        final DisplayPolicy displayPolicy = displayContent.getDisplayPolicy();
        displayPolicy.adjustWindowParamsLw(win, win.mAttrs, callingPid, callingUid);
        // 创建InputChanel,用于input事件的传递和接收
        if  (openInputChannels) {
            win.openInputChannel(outInputChannel);
        }

        // From now on, no exceptions or errors allowed!
        res = WindowManagerGlobal.ADD_OKAY;


        ....
        win.attach();  // 与SF创建联系,通信
        
        mWindowMap.put(client.asBinder(), win); // 将Windowstate和IWindow添加到mWindowMap中


        // 将WindowToken向下转型
        final ActivityRecord tokenActivity = token.asActivityRecord();
        boolean imMayMove = true;
        // 将WindowState对象添加到WindowToken中,WindowToken将作为WindowState的父容器
        win.mToken.addWindow(win);

        // 对TYPE_APPLICATION_STARTING, TYPE_INPUT_METHOD, TYPE_INPUT_METHOD_DIALOG, TYPE_WALLPAPER(displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER)特殊窗口处理

        // 窗口动画对象 
        final WindowStateAnimator winAnimator = win.mWinAnimator;
        winAnimator.mEnterAnimationPending = true;
        winAnimator.mEnteringAnimation = true;
        .....
        // 设置Inset
        outInsetsState.set(win.getInsetsState(), win.isClientLocal());
        // 将InputMonitor#mUpdateInputWindowsNeeded属性设置为true,表示将更新Input内部
        displayContent.getInputMonitor().setUpdateInputWindowsNeededLw();

        boolean focusChanged = false;
        //  如果能收到按键
        if (win.canReceiveKeys()) {
            // 更新焦点窗口
            focusChanged = updateFocusedWindowLocked(UPDATE_FOCUS_WILL_ASSIGN_LAYERS,
                    false /*updateInputWindows*/);
            if (focusChanged) {
                imMayMove = false;
            }
        }
        // 为该WindowState分配layer,但是此次并不会真正地为分配layer
        win.getParent().assignChildLayers();
        // 更新Input Window
        if (focusChanged) {
            displayContent.getInputMonitor().setInputFocusLw(displayContent.mCurrentFocus,
                    false /*updateInputWindows*/);
        }
        displayContent.getInputMonitor().updateInputWindowsLw(false /*force*/);

        // 如果方向有更新,更新全局配置
        if (win.isVisibleOrAdding() && displayContent.updateOrientation()) {
            displayContent.sendNewConfiguration();
        }
        
        getInsetsSourceControls(win, outActiveControls);
    }
    return res;
}

以上方法中,先进行了大量的验证,如果验证成功,则进入开始做进一步的处理。这里省略去了一些针对特殊窗口的处理,所做工作主要如下:

  • 根据传入的attrs.token,从DisplayContent#mTokenMap<IBinder, WindowToken>中获取WindowToken对象,如果获取不到,则会创建新的WindowToken;
  • 创建WindowState对象;
  • 将WindowState对象添加到WindowToken中,WindowToken将成为WindowState对象的父容器;
    创建InputChannel,用于input事件派发;
  • 更新焦点窗口;
  • 更新InputWindow;
2.2.1 创建WindowToken对象

WindowToken作为WindowState的父容器,负责管理一组Window。Window添加过程中,WindowToken的创建是视情况而定的,因为一个WindowToken管理着一组Window,如果在添加Window的过程中,已经存在合适的WindowToken,那么就不会创建,否则会创建WindowToken。
WindowToken的构造方法如下:

// frameworks/base/services/core/java/com/android/server/wm/WindowToken.java
WindowToken(WindowManagerService service, IBinder _token, int type, boolean persistOnEmpty,
            DisplayContent dc, boolean ownerCanManageAppTokens, int ownerUid,
            boolean roundedCornerOverlay, boolean fromClientToken) {
    super(service);
    token = _token;  // IBinder对象,作为一组窗口的实际token
    windowType = type;   // 窗口类型
    mPersistOnEmpty = persistOnEmpty;     // 是否是显示添加的WindowToken
    mOwnerCanManageAppTokens = ownerCanManageAppTokens;  // 是否具有MANAGE_APP_TOKENS权限
    mOwnerUid = ownerUid;  // owner id
    mRoundedCornerOverlay = roundedCornerOverlay;  // 是否覆盖圆角
    mFromClientToken = fromClientToken;
    if (dc != null) {
        dc.addWindowToken(token, this);    // 将该对象添加到DisplayContent中   关键layerTree
    }
    if (shouldReportToClient()) {
        try {
            mDeathRecipient = new DeathRecipient();
            mDeathRecipient.linkToDeath();
        } catch (RemoteException e) {
            Slog.e(TAG, "Unable to add window token with type " + windowType + " on "
                    + "display " + dc.getDisplayId(), e);
            mDeathRecipient = null;
            return;
        }
    }
}

以上方法中,在对一些属性进行初始化后,将WindowToken和对应的IBinder对象传递给DisplayContent,并以<IBinder, WindowToken>的形式,保存在DisplayContent#mToken中,同时将Token放置在合适的容器中:

2.2.2 addWindowToken()添加windowToken
void addWindowToken(IBinder binder, WindowToken token) {
    // 如果该WindowToken已经关联有DisplayContent对象,则不能再关联其他DisplayContent对象
    final DisplayContent dc = mWmService.mRoot.getWindowTokenDisplay(token);
    .....
    
    // 将WindowToken添加到DisplayContent#mTokenMap中
    mTokenMap.put(binder, token);
    
    // 对于非Activity类型的窗口,会根据Window类型添加到对应三个container中
    if (token.asActivityRecord() == null) {
        // Set displayContent for non-app token to prevent same token will add twice after
        // onDisplayChanged.
        // TODO: Check if it's fine that super.onDisplayChanged of WindowToken
        //  (WindowsContainer#onDisplayChanged) may skipped when token.mDisplayContent assigned.
        // WindowToken和DisplayContent关联
        token.mDisplayContent = this;
        // Add non-app token to container hierarchy on the display. App tokens are added through
        // the parent container managing them (e.g. Tasks).
        switch (token.windowType) {
            // 将输入法Window,放在mImeWindowsContainers中
            case TYPE_INPUT_METHOD:
            case TYPE_INPUT_METHOD_DIALOG:
                mImeWindowsContainers.addChild(token);
                break;
            case TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY:
                // TODO(display-area): Migrate to DisplayArea
                mOverlayContainers.addChild(token);
                break;
            default:
                mDisplayAreaPolicy.addWindow(token); // 其他类型Window,放在mDisplayAreaPolicy
                break;
        }
    }
}

以上方法中,mImeWindowsContainers、mOverlayContainers和mDisplayAreaPolicy将作为WindowToken的父容器对其进行管理,其中:

  • mImeWindowsContainers:ImeContainer类对象,作为IME窗口的父容器,管理IME窗口;
  • mOverlayContainers:NonAppWindowContainers类对象,作为和应用不关联的窗口的父容器,如状态栏等;
  • mDisplayAreaPolicy: DisplayAreaPolicy类对象,它本身并非容器,但该对象作为策略会持有一个合适的容器,这个容器就是DisplayArea.Token, 来管理其他类型的窗口;
2.2.3 创建WindowState对象

在得到WindowToken对象后,接下来将创建WindowState对象,一个WindowState代表了一个具体的Window,每添加一个Window,都会创建对应的WindowState对象。
计算BaseLayer和SubLayer值,并将sub-window添加到parent-window中
parentWindow.addChild(this, sWindowSubLayerComparator);

WindowState类的构造方法如下:

WindowState(WindowManagerService service, Session s, IWindow c, WindowToken token,
            WindowState parentWindow, int appOp, int seq, WindowManager.LayoutParams a,
            int viewVisibility, int ownerId, int showUserId,
            boolean ownerCanAddInternalSystemWindow, PowerManagerWrapper powerManagerWrapper) {
    super(service);   // 执行WindowContainer(wms)
    mSession = s;    // Session对象  
    mClient = c;     // 客户端的IWindow类型对象,该对象和客户端进行交互
    mAppOp = appOp;
    mToken = token;  // WindowToken对象 
    mActivityRecord = mToken.asActivityRecord();    // 该token如果是ActivityRecord类型,则相当于向下转型
    mOwnerUid = ownerId;
    mShowUserId = showUserId;
    mOwnerCanAddInternalSystemWindow = ownerCanAddInternalSystemWindow;
    mWindowId = new WindowId(this);
    mAttrs.copyFrom(a);  // 从传入的attr对象复制给mAttrs对象
    mLastSurfaceInsets.set(mAttrs.surfaceInsets);
    mViewVisibility = viewVisibility;  // 窗口可见性
    mPolicy = mWmService.mPolicy;  // PhoneWindowManager对象
    mContext = mWmService.mContext;
    DeathRecipient deathRecipient = new DeathRecipient();
    mSeq = seq;
    mPowerManagerWrapper = powerManagerWrapper;
    mForceSeamlesslyRotate = token.mRoundedCornerOverlay;  // 圆角窗口的特殊标记,控制圆角的方向旋转
    
    ......
    
    mDeathRecipient = deathRecipient;
    // 对Sub Window类型窗口设置BaseLayer和SubLayer值
    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;

        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 {  // 对非子窗口类型窗口设置BaseLayer和SubLayer值
        // 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;
    }
    // 是否为"漂浮"类窗口,因为该俩窗口需要挂在其他窗口上显示
    mIsFloatingLayer = mIsImWindow || mIsWallpaper;

    if (mActivityRecord != null && mActivityRecord.mShowForAllUsers) {
        // Windows for apps that can show for all users should also show when the device is
        // locked.
        mAttrs.flags |= FLAG_SHOW_WHEN_LOCKED;  //锁屏可见
    }

    mWinAnimator = new WindowStateAnimator(this);  // 创建WindowStateAnimator对象

    // 创建InputWindowHandle对象
    mInputWindowHandle = new InputWindowHandle(
            mActivityRecord != null
                    ? mActivityRecord.getInputApplicationHandle(false /* update */) : null,
                getDisplayId());

    // Make sure we initial all fields before adding to parentWindow, to prevent exception
    // during onDisplayChanged.
    // 如果是子窗口类型窗口,需要添加到父窗口中
    if (mIsChildWindow) {
        ProtoLog.v(WM_DEBUG_ADD_REMOVE, "Adding %s to %s", this, parentWindow);
        parentWindow.addChild(this, sWindowSubLayerComparator);
    }

    // System process or invalid process cannot register to display config change.
    // 获取WindowProcessController对象,管理进程
    mWpcForDisplayConfigChanges = (s.mPid == MY_PID || s.mPid < 0)
            ? null
            : service.mAtmService.getProcessController(s.mPid, s.mUid);
}

在以上方法中,对WindState类中的许多属性进行了初始化操作,其中还创建了两个对象——WindowStateAnimator对象和InputWindowHandle对象。
WindowStateAnimator对象用来为WindowState对象进行动画和Surface的转变操作,绘制过程中,动画的状态和Surface状态都会由该对象来进行记录。
InputWindowHandle对象则用于input事件的分发,通过内部的IBinder类型的token,将InputChannel和WindowState进行关联。

parentWindow.addChild(this, sWindowSubLayerComparator);
// 添加子窗口 sWindowSubLayerComparator
// 直接根据subLayer进行比较

2.2.4 将WindowToken设置为WindowState的父容器

通过WindowToken#addWindow()方法,将WindowState对象添加到WindowToken中,使得WindowToken成为WindowState的父容器:

void addWindow(final WindowState win) {
   
    // 对于子窗口而言,由父窗口管理,不需要由WindowToken管理
    if (win.isChildWindow()) {
        // Child windows are added to their parent windows.
        return;
    }
    // This token is created from WindowContext and the client requests to addView now, create a
    // surface for this token.
    // 如果mSurfaceControl不存在创建createSurfaceControl对象
    if (mSurfaceControl == null) {
        createSurfaceControl(true /* force */);
        // Layers could have been assigned before the surface was created, update them again
        reassignLayer(getSyncTransaction());
    }
    // 添加到mChildren列表中,并设置WindowStack#mParent为该WindowToken
    if (!mChildren.contains(win)) {
        ProtoLog.v(WM_DEBUG_ADD_REMOVE, "Adding %s to %s", win, this);
        addChild(win, mWindowComparator);
        mWmService.mWindowsChanged = true;
        // TODO: Should we also be setting layout needed here and other places?
    }
}


/**
* Compares two child window of this token and returns -1 if the first is lesser than the
* second in terms of z-order and 1 otherwise.
*/
private final Comparator<WindowState> mWindowComparator =
    (WindowState newWindow, WindowState existingWindow) -> {
final WindowToken token = WindowToken.this;

return isFirstChildWindowGreaterThanSecond(newWindow, existingWindow) ? 1 : -1;
};
// 比较mBaseLayer
protected boolean isFirstChildWindowGreaterThanSecond(WindowState newWindow,
        WindowState existingWindow) {
    // New window is considered greater if it has a higher or equal base layer.
    return newWindow.mBaseLayer >= existingWindow.mBaseLayer;
}

通过addChild()方法,将WindowState对象添加到WindowToken#mChildren列表中,同时将WindowToken赋值给WindowState#mParent属性。

2.2.5 通过win.attach方法与SF建立连接
void attach() {
        if (DEBUG) Slog.v(TAG, "Attaching " + this + " token=" + mToken);
        mSession.windowAddedLocked(mAttrs.packageName);
    }

void windowAddedLocked(String packageName) {
        mPackageName = packageName;
        mRelayoutTag = "relayoutWindow: " + mPackageName;
        if (mSurfaceSession == null) {
            ......
            mSurfaceSession = new SurfaceSession();  //一个window对应一个,调到native层创建SurfaceComposerClient
            ......
            mService.mSessions.add(this);
            if (mLastReportedAnimatorScale != mService.getCurrentAnimatorScale()) {
                mService.dispatchNewAnimatorScaleLocked(this);
            }
        }
        mNumWindow++;
    }

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

调用到native层 SurfaceComposerClient负责app进程与SF通信 第一次引用会调用onFirstRef SurfaceComposerClient : public RefBase

static jlong nativeCreate(JNIEnv* env, jclass clazz) {
    SurfaceComposerClient* client = new SurfaceComposerClient();
    client->incStrong((void*)nativeCreate);  // 第一次引用触发onFirstRef做一些初始化工作
    return reinterpret_cast<jlong>(client);
}

void SurfaceComposerClient::onFirstRef() {
    // 通过 ComposerService 拿到了一个 ISurfaceComposer
    sp<ISurfaceComposer> sf(ComposerService::getComposerService());
    if (sf != nullptr && mStatus == NO_INIT) {
        sp<ISurfaceComposerClient> conn;
        conn = sf->createConnection();  // 获取SurfaceFlinger的Binder对象调用createConnection
        if (conn != nullptr) {
            mClient = conn;
            mStatus = NO_ERROR;
        }
    }
}

ComposerService 它是一个单例,这里通过 getComposerService 拿到一个 sp 对象。这是一个 ISurfaceComposer 的强智能指针。
前面我们已经介绍了 ISurfaceComposer,它是 SF 的借口,在 App 端会有它的代理对象。

ComposerService::ComposerService()
: Singleton<ComposerService>() {
    Mutex::Autolock _l(mLock);
    connectLocked(); 
}

bool ComposerService::connectLocked() {
    const String16 name("SurfaceFlinger");
    mComposerService = waitForService<ISurfaceComposer>(name);
    if (mComposerService == nullptr) {
        return false; // fatal error or permission problem
    }

    // Create the death listener.
    class DeathObserver : public IBinder::DeathRecipient {
        ComposerService& mComposerService;
        virtual void binderDied(const wp<IBinder>& who) {
            ALOGW("ComposerService remote (surfaceflinger) died [%p]",
                  who.unsafe_get());
            mComposerService.composerServiceDied();
        }
     public:
        explicit DeathObserver(ComposerService& mgr) : mComposerService(mgr) { }
    };

    mDeathObserver = new DeathObserver(*const_cast<ComposerService*>(this));
    IInterface::asBinder(mComposerService)->linkToDeath(mDeathObserver);
    return true;
}

当通过 ServiceManager 拿到 SF 的Binder 对象之后,就通过 Binder 对象和 SF 建立连接。

接下来看createConnection返回的具体对象: 返回了一个Client对象

sp<ISurfaceComposerClient> SurfaceFlinger::createConnection() {
    const sp<Client> client = new Client(this);
    return client->initCheck() == NO_ERROR ? client : nullptr;
}

在 SurfaceComposerClient 的 onFirstRef 中创建的 mClient 对象,其实就是系统进程中的 BnSurfaceComposerClient。而它的实现类,就是 Client。

[frameworks/native/services/surfaceflinger/Client.h]  
class Client : public BnSurfaceComposerClient  
sp mFlinger;