#上层Client和SurfaceFlinger的交互
为了很好的切入主题,我们这里基于Native的Framework进行应用的开发呢,不是指的NDK应用。我们直接用系统接口,进行开发。Native应用直接抛弃掉Android的Java上层,AMS,WMS,View等,直接在Native开发,这样便于我们理解显示系统。
Native应用建立
在显示子系统中,Surface是一个很重要的类,通过Surface我们就能获取到Buffer,我们就能够和Android Native窗口系统建立连接。我们就基于Surface来写一个Native的应用。
首先,我们先定义一个封装类WindowSurfaceWrapper,WindowSurfaceWrapper和Surface进行交互。
class WindowSurfaceWrapper : public RefBase {
public:
// Creates the window.
WindowSurfaceWrapper(const String8& name);
virtual ~WindowSurfaceWrapper() {}
virtual void onFirstRef();
// Retrieves a handle to the window.
sp<ANativeWindow> getSurface() const;
int width() {
return mWidth;
}
int height() {
return mHeight;
}
private:
WindowSurfaceWrapper(const WindowSurfaceWrapper&);
WindowSurfaceWrapper& operator=(const WindowSurfaceWrapper&);
sp<SurfaceControl> mSurfaceControl;
int mWidth;
int mHeight;
String8 mName;
};
WindowSurfaceWrapper对应的实现如下:
WindowSurfaceWrapper::WindowSurfaceWrapper(const String8& name) {
mName = name;
}
void WindowSurfaceWrapper::onFirstRef() {
status_t err;
sp<SurfaceComposerClient> surfaceComposerClient = new SurfaceComposerClient;
err = surfaceComposerClient->initCheck();
if (err != NO_ERROR) {
fprintf(stderr, "SurfaceComposerClient::initCheck error: %#x\n", err);
return;
}
// Get main display parameters.
sp<IBinder> mainDisplay = SurfaceComposerClient::getBuiltInDisplay(
ISurfaceComposer::eDisplayIdMain);
DisplayInfo mainDisplayInfo;
err = SurfaceComposerClient::getDisplayInfo(mainDisplay, &mainDisplayInfo);
if (err != NO_ERROR) {
fprintf(stderr, "ERROR: unable to get display characteristics\n");
return;
}
uint32_t width, height;
if (mainDisplayInfo.orientation != DISPLAY_ORIENTATION_0 &&
mainDisplayInfo.orientation != DISPLAY_ORIENTATION_180) {
// rotated
width = mainDisplayInfo.h;
height = mainDisplayInfo.w;
} else {
width = mainDisplayInfo.w;
height = mainDisplayInfo.h;
}
sp<SurfaceControl> surfaceControl = surfaceComposerClient->createSurface(
mName, width, height,
PIXEL_FORMAT_RGBX_8888, ISurfaceComposerClient::eOpaque);
if (surfaceControl == NULL || !surfaceControl->isValid()) {
fprintf(stderr, "Failed to create SurfaceControl\n");
return;
}
SurfaceComposerClient::Transaction{}
.setLayer(surfaceControl, 0x7FFFFFFF)
.show(surfaceControl)
.apply();
mSurfaceControl = surfaceControl;
mWidth = width;
mHeight = height;
}
sp<ANativeWindow> WindowSurfaceWrapper::getSurface() const {
sp<ANativeWindow> anw = mSurfaceControl->getSurface();
return anw;
}
getSurface
获取Native 窗口,这个窗口能够和Native的窗口系统建立联系,我们直接往这个窗口里面绘制我们需要的界面就OK了。
int main(int argc, char *argv[]) {
unsigned samples = 0;
printf("usage: %s [samples]\n", argv[0]);
if (argc == 2) {
samples = atoi( argv[1] );
printf("Multisample enabled: GL_SAMPLES = %u\n", samples);
}
sp<ProcessState> proc(ProcessState::self());
ProcessState::self()->startThreadPool();
sp<WindowSurfaceWrapper> windowSurface(new WindowSurfaceWrapper(String8("NativeBinApp")));
drawNativeWindow(windowSurface->getSurface().get(), windowSurface->width(), windowSurface->height());
IPCThreadState::self()->joinThreadPool();
return EXIT_SUCCESS;
}
解释一下代码中的关键点:
- 创建一个SurfaceComposerClient,这是应用端,是SurfaceFlinger的Client端,它将建立和SurfaceFlinger服务的通信
- getDisplayInfo,获取手机屏幕的信息
- createSurface,创建SurfaceControl,在SurfaceFlinger创建对应的Layer等~
- setLayer,设置窗口的z-Oder,SurfaceFlinger根据z-Oder决定窗口的可见性及可见大小
- show,让当前窗口可见
- apply,这时,上面的设置的属性才真正生效,传给SurfaceFlinger
至于怎么画界面,我们接来下再介绍,稍后再给出drawNativeWindow的代码。我们先来看,目前都干了什么。
应用和SurfaceFlinger的链接建立
应用和SurfaceFlinger是两个不同的进程,他们采用Binder通信,应用是Client端,SurfaceFlinger是服务端。在Android中ProcessState是客户端和服务端公共的部分,作为Binder通信的基础,ProcessState是一个singleton类,每个进程只有一个对象,这个对象负责打开Binder驱动,建立线程池,让其进程里面的所有线程都能通过Binder通信。与之相关的是IPCThreadState,每个线程都有一个IPCThreadState实例登记在Linux线程的上下文附属数据中,主要负责Binder的读取,写入和请求处理框架。IPCThreadState在构造的时候获取进程的ProcessState并记录在自己的成员变量mProcess中,通过mProcess可以获得Binder的句柄。
我们这里将不详细的介绍Binder。有需求的可以提,我们开一个专题。
SurfaceComposerClient的 定义非常简单,继承RefBase~,这样我们就可以直接用智能指针sp,wp管理SurfaceComposerClient对象,不用担心SurfaceComposerClient对象的回收问题。
智能指针sp,wp,我们这里也不做详细的介绍,有需求的可以提,我们开一个专题。
在SurfaceComposerClient的构造函数中,只初始化了一个装mStatus。
SurfaceComposerClient::SurfaceComposerClient()
: mStatus(NO_INIT)
{
}
第一次引用的时候,才真正的建立连接:
*frameworks/native/libs/gui/SurfaceComposerClient.cpp
void SurfaceComposerClient::onFirstRef() {
sp<ISurfaceComposer> sf(ComposerService::getComposerService());
if (sf != 0 && mStatus == NO_INIT) {
auto rootProducer = mParent.promote();
sp<ISurfaceComposerClient> conn;
conn = (rootProducer != nullptr) ? sf->createScopedConnection(rootProducer) :
sf->createConnection();
if (conn != 0) {
mClient = conn;
mStatus = NO_ERROR;
}
}
}
ComposerService继承模板类Singleton,ComposerService是一个单例。
ComposerService::ComposerService()
: Singleton<ComposerService>() {
Mutex::Autolock _l(mLock);
connectLocked();
}
ComposerService在构建时,创建链接:
void ComposerService::connectLocked() {
const String16 name("SurfaceFlinger");
while (getService(name, &mComposerService) != NO_ERROR) {
usleep(250000);
}
assert(mComposerService != NULL);
// 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);
}
建立连接时,采用轮循的方式,getService时,如果SurfaceFlinger服务还没有启动,等待250000后再查询,知道等到SurffaceFlinger进程启动。DeathObserver是监听SurfaceFlinger进程是否死掉,做善后处理的。
getComposerService直接返回单实例mComposerService。
/*static*/ sp<ISurfaceComposer> ComposerService::getComposerService() {
ComposerService& instance = ComposerService::getInstance();
Mutex::Autolock _l(instance.mLock);
if (instance.mComposerService == NULL) {
ComposerService::getInstance().connectLocked();
assert(instance.mComposerService != NULL);
ALOGD("ComposerService reconnected");
}
return instance.mComposerService;
}
createScopedConnection函数,将建立和SurfaceFlinger的连接。
void SurfaceComposerClient::onFirstRef() {
sp<ISurfaceComposer> sf(ComposerService::getComposerService());
if (sf != 0 && mStatus == NO_INIT) {
auto rootProducer = mParent.promote();
sp<ISurfaceComposerClient> conn;
conn = (rootProducer != nullptr) ? sf->createScopedConnection(rootProducer) :
sf->createConnection();
if (conn != 0) {
mClient = conn;
mStatus = NO_ERROR;
}
}
}
对于我们这里的使用来说,rootProducer是nullptr,所以直接走的sf->createConnection()。Bn端SurfaceFlinger的实现为:
* frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
sp<ISurfaceComposerClient> SurfaceFlinger::createConnection() {
return initClient(new Client(this));
}
static sp<ISurfaceComposerClient> initClient(const sp<Client>& client) {
status_t err = client->initCheck();
if (err == NO_ERROR) {
return client;
}
return nullptr;
}
Client继承BnSurfaceComposerClient,是ISurfaceComposerClient的Bn端。
我们来看一下,显示系统中,Client和SurfaceFlinger的关系:
应用端SurfaceComposerClient通过接口ISurfaceComposerClient和SurfaceFlinger的Client建立联系。应用端通过的ComposerService通过ISurfaceComposer和SurfaceFlinger建立联系。
SurfaceFlinger的启动
SurfaceFlinger是一个系统级的服务,Android系统启动的过程中就会启动SurfaceFlinger,在初始化init时。
* frameworks/native/services/surfaceflinger/surfaceflinger.rc
service surfaceflinger /system/bin/surfaceflinger
class core animation
user system
group graphics drmrpc readproc
onrestart restart zygote
writepid /dev/stune/foreground/tasks
socket pdx/system/vr/display/client stream 0666 system graphics u:object_r:pdx_display_client_endpoint_socket:s0
socket pdx/system/vr/display/manager stream 0666 system graphics u:object_r:pdx_display_manager_endpoint_socket:s0
socket pdx/system/vr/display/vsync stream 0666 system graphics u:object_r:pdx_display_vsync_endpoint_socket:s0
既然是独立的进程,系统级的服务,那就有自己的main函数:
* frameworks/native/services/surfaceflinger/main_surfaceflinger.cpp
int main(int, char**) {
startHidlServices();
signal(SIGPIPE, SIG_IGN);
// When SF is launched in its own process, limit the number of
// binder threads to 4.
ProcessState::self()->setThreadPoolMaxThr