【Graphics & SF】【初始化】1、App到SurfaceFlinger的连接【Android 12】

2,280 阅读7分钟

不管是通过启动Activity的方式来创建App类型的窗口,还是通过主动调用WindowManager.addView的方式来创建非App类型的窗口,流程都是一样,最终都是通过ViewRootImpl与WMS通信来创建一个窗口。

从App进程创建第一个窗口开始,分析App是如何与SurfaceFlinger服务建立起连接的。

1 ViewRootImpl.setView

    /**
     * We have one child
     */
    public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView,
            int userId) {
        synchronized (this) {
            if (mView == null) {
				// ......
                try {
					// ......
                    res = mWindowSession.addToDisplayAsUser(mWindow, mWindowAttributes,
                            getHostVisibility(), mDisplay.getDisplayId(), userId,
                            mInsetsController.getRequestedVisibility(), inputChannel, mTempInsets,
                            mTempControls);
                    // ......
	}

这里调用mWindowSession.addToDisplayAsUser向WindowManager添加一个窗口。

ViewRootImpl的成员变量mWindowSession在ViewRootImpl创建的时候初始化,通过static类型的WindowManagerGlobal.getWindowSession方法得到:

    @UnsupportedAppUsage
    public static IWindowSession getWindowSession() {
        synchronized (WindowManagerGlobal.class) {
            if (sWindowSession == null) {
                try {
                    // Emulate the legacy behavior.  The global instance of InputMethodManager
                    // was instantiated here.
                    // TODO(b/116157766): Remove this hack after cleaning up @UnsupportedAppUsage
                    InputMethodManager.ensureDefaultInstanceForDefaultDisplayIfNecessary();
                    IWindowManager windowManager = getWindowManagerService();
                    sWindowSession = windowManager.openSession(
                            new IWindowSessionCallback.Stub() {
                                @Override
                                public void onAnimatorScaleChanged(float scale) {
                                    ValueAnimator.setDurationScale(scale);
                                }
                            });
                } catch (RemoteException e) {
                    throw e.rethrowFromSystemServer();
                }
            }
            return sWindowSession;
        }
    }

可以看到WindowManagerGlobal.sWindowSession是单例的。

IWIndowSession接口的定义是:

/**
 * System private per-application interface to the window manager.
 *
 * {@hide}
 */
interface IWindowSession {

是每一个App进程与WindowManager的交互的接口。

2 Session.addToDisplayAsUser

IWindowSession的服务端实现是Session类:

/**
 * This class represents an active client session.  There is generally one
 * Session object per process that is interacting with the window manager.
 */
class Session extends IWindowSession.Stub implements IBinder.DeathRecipient {

Session类代表了一个活跃的客户端会话。通常是每一个和WindowManager交互的进程有一个Session对象。

    @Override
    public int addToDisplayAsUser(IWindow window, WindowManager.LayoutParams attrs,
            int viewVisibility, int displayId, int userId, InsetsState requestedVisibility,
            InputChannel outInputChannel, InsetsState outInsetsState,
            InsetsSourceControl[] outActiveControls) {
        return mService.addWindow(this, window, attrs, viewVisibility, displayId, userId,
                requestedVisibility, outInputChannel, outInsetsState, outActiveControls);
    }

这里继续调用了WindowManagerService.addWindow方法去添加窗口。

3 WindowManagerService.addWindow

    public int addWindow(Session session, IWindow client, LayoutParams attrs, int viewVisibility,
            int displayId, int requestUserId, InsetsState requestedVisibility,
            InputChannel outInputChannel, InsetsState outInsetsState,
            InsetsSourceControl[] outActiveControls) {
		// ......
        synchronized (mGlobalLock) {
        	// ......
			final WindowState win = new WindowState(this, session, client, token, parentWindow,
                    appOp[0], attrs, viewVisibility, session.mUid, userId,
                    session.mCanAddInternalSystemWindow);
            // ......	
            win.attach();
            // ......
        }
        // ......
    }

首先基于这个Session对象创建了一个WindowState对象,然后调用WindowState.attach方法。

4 WindowState.attach

    void attach() {
        if (DEBUG) Slog.v(TAG, "Attaching " + this + " token=" + mToken);
        mSession.windowAddedLocked();
    }

mSession就是上面一直提到的那个Session对象,这里调用Session.windowAddedLocked方法。

5 Session.windowAddedLocked

    void windowAddedLocked() {
		// ......
        if (mSurfaceSession == null) {
            if (DEBUG) {
                Slog.v(TAG_WM, "First window added to " + this + ", creating SurfaceSession");
            }
            mSurfaceSession = new SurfaceSession();
            ProtoLog.i(WM_SHOW_TRANSACTIONS, "  NEW SURFACE SESSION %s", mSurfaceSession);
            mService.mSessions.add(this);
            if (mLastReportedAnimatorScale != mService.getCurrentAnimatorScale()) {
                mService.dispatchNewAnimatorScaleLocked(this);
            }
        }
        mNumWindow++;
    }

如果是该进程第一次添加窗口,这里的mSurfaceSession应该是NULL。那么这里首先会创建一个SurfaceSession对象,然后保存到Session的SurfaceSession类型的成员变量mSurfaceSession中。这里看到SurfaceSession也是单例的。

SurfaceSession类的定义是:

/**
 * 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 {

SurfaceSession的一个实例代表了一个与SurfaceFlinger的连接,通过这个连接你可以创建一个或者多个将会合成到屏幕的Surface。

6 SurfaceSession.init

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

SurfaceSession的构造方法很简单,调用JNI层的相关接口nativeCreate来创建一个到SurfaceFlinger的连接,用long型的成员变量mNativeClient保存从底层返回的一个指向SurfaceComposerClient的指针地址。

7 android_view_SurfaceSession.nativeCreate

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

1)、首先创建一个SurfaceComposerClient对象。

SurfaceComposerClient的构造函数很简单,初始化了一个状态值为NO_INIT:

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

2)、接着调用RefBase.incStrong增加强引用计数,这会导致SurfaceComposerClient的onFirstRef函数被调用。

onFirstRef函数的调用原理则是涉及到了c++智能指针的概念。

查阅资料:blog.csdn.net/lewif/artic…

首先sp和wp是针对c++而设计的,因为Java根本就没有指针的概念,替使用者减少了很多不必要的麻烦。在指针的使用过程中,如果处理不妥当,甚至会出现程序的崩溃:

  1. 指针没有初始化;
  2. new了对象后没有delete;
  3. ptr1 和 ptr2同时指向了对象A,当释放了ptr1,同时ptr1=NULL后,ptr2并不知道它所指向的对象不存在了。 关于对象存在多个引用的问题, android设计了两个引用计数相关的类,LightRefBase和RefBase。我们能够想到对象的引用计数应该是保存在对象中的,所以我们在使用引用计数类时,只需要让普通类去继承LightRefBase和RefBase即可,这样普通类产生的对象中就自然而然拥有了引用计数。

关于对象存在多个引用的问题, android设计了两个引用计数相关的类,LightRefBase和RefBase。我们能够想到对象的引用计数应该是保存在对象中的,所以我们在使用引用计数类时,只需要让普通类去继承LightRefBase和RefBase即可,这样普通类产生的对象中就自然而然拥有了引用计数。

在frameworks中有部分类都实现了onFirstRef函数(需要使用智能指针的类重写了父类RefBase的onFirstRef函数),这个非常有用,当强指针在第一次引用的时候,会去调用这个函数。

由于SurfaceComposerClient类是继承RefBase的:

class SurfaceComposerClient : public RefBase

那么这里我们创建了一个SurfaceComposerClient对象,然后赋值给局部变量client,接着调用父类RefBase的incStrong函数,这时候会增加强引用计数,导致SurfaceComposerClient的onFirstRef()函数得到调用。

3)、最后使用reinterpret_cast将指向刚刚创建的SurfaceComposerClient对象的指针转换为一个整型返回给上层的SurfaceSession。

8 SurfaceComposerClient.onFirstRef

void SurfaceComposerClient::onFirstRef() {
    sp<ISurfaceComposer> sf(ComposerService::getComposerService());
    if (sf != nullptr && mStatus == NO_INIT) {
        sp<ISurfaceComposerClient> conn;
        conn = sf->createConnection();
        if (conn != nullptr) {
            mClient = conn;
            mStatus = NO_ERROR;
        }
    }
}

这个函数主要涉及两个方面的内容:

1)、获取到ISurfaceComposer的代理对象。

2)、调用ISurfaceComposer.createConnection方法建立起到SurfaceFlinger的连接。

8.1 获取ISurfaceComposer的代理对象

这里是调用了ComposerService.getComposerService来获取ISurfaceComposer的远程代理对象:

/*static*/ sp<ISurfaceComposer> ComposerService::getComposerService() {
    ComposerService& instance = ComposerService::getInstance();
    Mutex::Autolock _l(instance.mLock);
    if (instance.mComposerService == nullptr) {
        if (ComposerService::getInstance().connectLocked()) {
            ALOGD("ComposerService reconnected");
        }
    }
    return instance.mComposerService;
}

因为ComposerService类是单例模式:

class ComposerService : public Singleton<ComposerService>

所以当我们第一次调用ComposerService的静态函数getInstance的时候,就会走进它的构造函数中:

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

这里又调用了ComposerService的connectLocked函数:

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

    // ......
}

这里调用了native层的ServiceManager去获取名为“SurfaceFlinger”的服务,这里能看到ISurfaceComposer的服务端实现便是SurfaceFlinger服务。

如果能够成功返回一个ISurfaceComposer对象,即BpSurfaceComposer类型的SurfaceFlinger服务的远程代理,那么将ComposerService的类型为sp<ISurfaceComposer>的成员变量mComposerService指向这个BpSurfaceComposer类型的代理对象。

这样SurfaceComposerClient后续便可以通过getComposerService函数直接拿到SurfaceFlinger的代理对象。

8.2 获取ISurfaceComposerClient的代理对象

回到SurfaceComposerClient.onFirstRef,经过8.1的操作,此时我们拿到了SurfaceFlinger服务的Binder代理对象,保存在了ComposerService的成员变量mComposerService中,它是BpSurfaceComposer类型的。

接着调用BpSurfaceComposer.createConnection函数来创建一个到SurfaceFlinger服务的连接,那么这最终会跨Binder来到BnSurfaceComposer处,即SurfaceFlinger:

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

这里看到在SurfaceFlinger,创建了一个Client类型的对象,传入的是SurfaceFlinger自己:

Client::Client(const sp<SurfaceFlinger>& flinger)
    : mFlinger(flinger)
{}

在Client内部则通过sp<SurfaceFlinger>类型的成员变量mFlinger保存了一个SurfaceFlinger的引用,Client也可以直接操作SurfaceFlinger。

Client是ISurfaceComposerClient的本地实现,即BnSurfaceComposerClient类型的:

class Client : public BnSurfaceComposerClient
class BnSurfaceComposerClient : public SafeBnInterface<ISurfaceComposerClient> {

返回给SurfaceComposerClient的则是BpSurfaceComposerClient类型的Binder代理对象,并保存在了SurfaceComposerClient的类型为sp<ISurfaceComposerClient>成员变量mClient中。

这样来看,Client算是每一个客户端进程在SurfaceFlinger服务端的一个代表,其数据结构相对简单,主要保存着属于该客户端进程的一些信息,如Layer信息:

    DefaultKeyedVector< wp<IBinder>, wp<Layer> > mLayers;

那么通过这一步,客户端进程通过在SurfaceFlinger创建了一个代表着该客户端进程的Client对象,算是在SurfaceFlinger处有了自己的一席之地,建立起了和SurfaceFlinger的连接。

9 总结

这个时候需要一张类图:

App到SurfaceFlinger的连接.png

1)、App通过IWindowSession接口和WindowManagerService进行交互,IWindowSession在服务端的实现是Session对象,每一个App进程在WindowManagerService都有一个对应的Session对象。

2)、App第一次添加窗口时,Session对象会创建一个SurfaceSession对象,SurfaceSession的构造方法中会调用JNI方法创建一个Native层的SurfaceComposerClient对象,并且SurfaceSession内部会有一个long型的成员变量持有这个SurfaceComposerClient对象的地址,后续上层便可以通过传入这个地址从而在Native层拿到这个SurfaceComposerClient对象。

3)、SurfaceComposerClient对象在初始化的时候会去建立与SurfaceFlinger的连接,一是通过ComposerService.getComposerService函数拿到SurfaceFlinger的远程代理对象并保存在ComposerService的成员变量mComposerService;二是通过ISurfaceComposer.createConnection在SurfaceFlinger处创建一个客户端进程的代表Client对象。