不管是通过启动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根本就没有指针的概念,替使用者减少了很多不必要的麻烦。在指针的使用过程中,如果处理不妥当,甚至会出现程序的崩溃:
- 指针没有初始化;
- new了对象后没有delete;
- 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 总结
这个时候需要一张类图:
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对象。