这篇文章主要描述从 Surface的创建,即客户数据是如何通过 Surface进行显示的。
一.从 Activity的创建说起
1.进程的创建
创建 Activity的过程,首先要从创建Activity所在的进程说起。在用户请求启动某个应用程序的时候,会调用 ActivityManagerService.startProcessLocked
ActivityManagerService.startProcessLocked
---->newProcessRecordLocked// 创建新的 ProcessRecord,每个经过ActivityManagerService 启动的进程都有一个 ProcessRecord,其中存储了进程相关的一切信息,所有这些 ProcessRecord都存储在AMS 中。
---->Process.start// 向SystemServer发起请求创建新的进程,并运行 ActivityThread.main
---->在AMS.mPidsSelfLocked 中添加新创建的 ProcessRecord,该变量负责管理ProcessRecord
ActivityThread.main
----->ActivityThread.attach
---->ActivityThread.handleLaunchActivity
从上述调用过程,我们可以看到所谓 ActivityThread.attach的过程,就是向它绑定的消息队列中添加消息的过程,但是这个添加的过程是通过服务端 ActivityManagerService完成的。ActivityThread 中有一个 ApplicationThread实例,这个类的定义如下:
private class ApplicationThread extends ApplicationThreadNative
其中 ApplicationThreadNative的定义如下:
public abstract class ApplicationThreadNative extends Binder implements IApplicationThread
由此可见, ApplicationThread是一个服务端,mgr.attachApplication(mAppThread);把它作为参数发送给ActivityManagerService, ActivityManagerService把它存储在ProcessRecord 的thread中,最后通过它向 ActivityThread的消息队列中添加消息来启动和 shedule Activity。ApplicationThread 起到了回调的作用。
特别说明的是 ActivityManagerService是在创建进程得到pid并把 ProcessRecord加入到mPidsSelfLocked 中之后,再在新创建的进程中运行 ActivityThread.main的
2.创建Activity
ActivityThread在收到LAUNCH_ACTIVITY 消息后,调用 handleLaunchActivity处理
frameworks/base/core/java/android/app/ActivityThread.java
handleLaunchActivity
----->performLaunchActivity
------>activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);
----->activity.attach(appContext, this, getInstrumentation(), r.token,
r.ident, app, r.intent, r.activityInfo, title, r.parent,
r.embeddedID, r.lastNonConfigurationInstances, config);
----->mWindow=PolicyManager.makeNewWindow(this);//mWindow 是Window类实例
----->com.android.internal.policy.impl.Policy.makeNewWindow
------>return new PhoneWindow(context);//PhoneWindow继承自 Window
----->mWindow.setWindowManager(null, mToken, mComponent.flattenToString()...
----->Window.setWindowManager
----->wm = WindowManagerImpl.getDefault();
----->mWindowManager = new LocalWindowManager(wm, hardwareAccelerated);
----->handleResumeActivity
r.window = r.activity.getWindow(); 这里get得到的 Window就是在activity.attach 中创建的 mWindow,即PhoneWindow
View decor = r.window.getDecorView();//window.getDecorView 接口的实现实际就是 PhoneWindow.getDecorView
frameworks/base/policy/src/com/android/internal/policy/impl/PhoneWindow.java
PhoneWindow.getDecorView
----->PhoneWindow.installDecor
----->mDecor = generateDecor();
----->return new DecorView(getContext(), -1);
----->mContentParent = generateLayout(mDecor);
----->View in = mLayoutInflater.inflate(layoutResource, null);
decor.addView(in, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);
这一句比较奇怪,凭空从哪里冒出来一个 ID_ANDROID_CONTENT,这就需要看layoutResource变量了,它一定是 layoutResource中定义的某个id,该值在不同情况下,有不同的赋值,它表示一个 layout,这些文件都定义在frameworks/base/core/res/res/layout/目录,他们有一个共同点就是,都有一个 FrameLayout,且android.id 属性都是 "@android.id/content"。这里的findViewById 显然是查找这个的,也就是说它返回的是一个 FrameLayout,也就是一个ViewGroup。
decor.setVisibility(View.INVISIBLE);
ViewManager wm = a.getWindowManager();// 从上面attach的过程就可以看到这里的 WindowManager就是LocalWindowManager
WindowManager.LayoutParams l = r.window.getAttributes();
a.mDecor = decor;
l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
l.softInputMode |= forwardBit;
if (a.mVisibleFromClient) {
a.mWindowAdded = true;
wm.addView(decor,l);
----->ViewRootImpl.setView// 每个ViewRootImpl对象中只有一个 View对象
}
这里的 wm就是 LocalWindowManager 类的实例,从下面的类图结构中,我们知道它继承自 WindowManagerImpl.CompatModeWrapper 类,它的addView 的实现就是调用 WindowManagerImpl.addView 。WindowManagerImpl 类中包含有一组 View 对象,一组ViewRootImpl 对象,每个 View 和ViewRootImpl 都是一一对应的。
3.Window,WindowManager ,ViewRootImpl
下面总结一下上述过程中类之间的关系,他们的类关系图如下:
首先, Activity中有一个PhoneWindow ,它从Window抽象类继承而来,它持有一个 DecorView,这里就要说道Window和 View之间的关系,Window类的注释如下:
* Abstract base class for a top-level window look and behavior policy. An
* instance of this class should be used as the top-level view added to the
* window manager. It provides standard UI policies such as a background, title
* area, default key processing, etc.
* The only existing implementation of this abstract class is
* android.policy.PhoneWindow, which you should instantiate when needing a
* Window. Eventually that class will be refactored and a factory method
* added for creating Window instances without knowing about a particular
* implementation.
Window是一个抽象类,它应该作为 top-level view添加到Window Manager 中,PhoneWindow是它的唯一实现, PhoneWindow持有一个DecorView 实例,它是这个 Window的top-level view ,它定义在 frameworks/base/policy/src/com/android/internal/policy/impl/PhoneWindow.java ,从类图中我们知道它是一个 FrameLayout,所以可以包含其他view。 FrameLayout继承自ViewGroup ,ViewGroup继承自 View,并实现了ViewManager 和ViewParent接口,这两个接口是有区别的, ViewManager提供了addView,removeView 的接口,用于管理 View,ViewParent 则用于和 parent打交道,例如向parent发送某种请求,如 requestLayout。
View当然是所有显示单元的基类。
二Surface的创建
1.IWindowSession的创建
Window类还有一个WindowManager 的引用, WindowManager类注释中说明context.getSystemService(Context.WINDOW_SERVICE)得到的就是一个WindowManager,它与 WindowService服务通信,但是WindowManager并没有从 Binder继承,这是怎么回事呢,原来, WindowManager的派生类WindowManagerImpl.CompatModeWrapper 中有一个 Display类,Display 中有一个 IWindowManager引用,显然这才是真正与 Window service通信的类。
WindowManagerImpl在进程中只有一个实例,在 WindowManagerImpl类中,包含有一组ViewRootImpl和 View的映射,ViewRootImpl.setView 方法中使用了 sWindowSession.add方法,其中sWindowSession 是一个static IWindowSession,由于它是 static的,所以在进程中它也只有一个实例。显然这个类是用于与服务器端通信的,它是与谁通信,它的功能如何呢?
在ViewRootImpl的构造函数中调用了 getWindowSession函数,ViewRootImpl.getWindowSession 定义如下:
public static IWindowSession getWindowSession(Looper mainLooper) {
synchronized (mStaticInit) {
if (!mInitialized) {
try {
InputMethodManager imm = InputMethodManager.getInstance(mainLooper);
sWindowSession = Display.getWindowManager().openSession(
imm.getClient(), imm.getInputContext());
mInitialized = true;
} catch (RemoteException e) {
}
}
return sWindowSession;
}
}
其中的 sWindowSession是IWindowSession 类型,这里显然是创建 sWindowSession的地方,Display.getWindowManager 的定义如下:
static IWindowManager getWindowManager() {
synchronized (sStaticInit) {
if (sWindowManager == null) {
sWindowManager = IWindowManager.Stub.asInterface(
ServiceManager.getService("window"));
}
return sWindowManager;
}
}
这里的 sWindowManager是IWindowManager 类型,IWindowManager.openSession定义如下:
public android.view.IWindowSession openSession(com.android.internal.view.IInputMethodClient client, com.android.internal.view.IInputContext inputContext) throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
android.view.IWindowSession _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeStrongBinder((((client!=null))?(client.asBinder()):(null)));
_data.writeStrongBinder((((inputContext!=null))?(inputContext.asBinder()):(null)));
mRemote.transact(Stub.TRANSACTION_openSession, _data, _reply, 0);// 这里显然是发送请求,并得到 reply响应。
_reply.readException();
_result = android.view.IWindowSession.Stub.asInterface(_reply.readStrongBinder());// 这里得到 IWindowSession的BpBinder ,通过asInterface得到 BpProxy
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
我们再来看在同一个文件中的服务器端的代码
case TRANSACTION_openSession:
{
data.enforceInterface(DESCRIPTOR);
com.android.internal.view.IInputMethodClient _arg0;
_arg0 = com.android.internal.view.IInputMethodClient.Stub.asInterface(data.readStrongBinder());
com.android.internal.view.IInputContext _arg1;
_arg1 = com.android.internal.view.IInputContext.Stub.asInterface(data.readStrongBinder());
android.view.IWindowSession _result = this.openSession(_arg0, _arg1);// 调用服务端的 openSession得到IWindowSession
reply.writeNoException();
reply.writeStrongBinder((((_result!=null))?(_result.asBinder()):(null)));
return true;
}
显然 this.openSession(_arg0, _arg1);是我们要找的代码,这里的 this就是WindowManagerService 类,因为它是从 IWindowManager.Stub继承的,在该类中
public IWindowSession openSession(IInputMethodClient client,
IInputContext inputContext) {
if (client == null) throw new IllegalArgumentException("null client");
if (inputContext == null) throw new IllegalArgumentException("null inputContext");
Session session = new Session(this, client, inputContext);
return session;
}
该函数返回了一个 Session,该类定义在frameworks/base/services/java/com/android/server/wm/Session.java,它继承自IWindowSession.Stub ,也就是说它是一个服务器端,当然通过 Binder之后,在客户端得到的是一个客户端 Binder。Session 中包含有 WindowManagerService的引用,这样,在客户端发起请求,在服务器端收到后,可以通过该引用调用 WindowManagerService的方法。
这样, ViewRootImpl.getWIndowSession就得到了一个进程唯一的 IWindowSession实例。
2.ViewRootImpl.setView
让我们从 ViewRootImpl.setView重新看起,它调用了sWindowSession.add 方法,即调用到服务端的 add代码,Session.add 代码如下
public int add(IWindow window, int seq, WindowManager.LayoutParams attrs,
int viewVisibility, Rect outContentInsets, InputChannel outInputChannel) {
return mService.addWindow(this, window, seq, attrs, viewVisibility, outContentInsets,
outInputChannel);
}
也即调用了 WindowManagerService.addWindow方法,在该方法中,
win = new WindowState(this, session, client, token,
attachedWindow, seq, attrs, viewVisibility);
。。。
win.attach();
----->mSession.windowAddedLocked();
----->mSurfaceSession = new SurfaceSession();
----->mService.mSessions.add(this);
。。。
mWindowMap.put(client.asBinder(), win);
WindowState是window manager 管理的window对象。它其中包含了 WindowManagerService引用,Session 引用,IWindow引用。 WindowManagerService引用显然是为了调用它提供的方法的, Session引用是为了表示进程的,因为它是进程唯一的,那么 IWindow引用的作用是什么呢?
我们从 ViewRootImpl.setView看起,它调用res = sWindowSession.add(mWindow, mSeq, mWindowAttributes,。。。)。这里的 mWindow的类型是W ,它在ViewRootImpl的构造函数中初始化
mWindow = new W(this);
W继承自IWindow.Stub ,IWindow.Stub在 IWindow.java中定义,它显然是个服务器端类,这样 IWindow的作用就很明显了,在addWindow的时候,它被添加到 WindowManagerService的WindowState 中,当然,在 binder传递的过程中,它变成了一个客户端类,在 WindowManagerService需要通知客户端程序发生某种事件的时候,就会调用 IWindow的接口,在这里有resized, dispatchAppVisibility,dispatchGetNewSurface ,windowFocusChanged,显然这种方法是 Android的Service 中经常采用的策略。 IWindow.Stub接口在每个ViewRootImpl 实例中,只有一个实例,它与 ViewRootImpl和View 都是一一对应的。也就是说 WindowState通过它就唯一标识了一个窗口。每个客户端进程对应一个 Session实例
在创建了 WindowState之后,调用了它的attach函数,其中调用了 Session.windowAddedLocked方法,它实际上就是创建了一个 SurfaceSession实例。这个实例后面创建 Surface的时候会用到,现在只要知道,它是 Session持有的,并且是一对一的关系,即一个客户进程是对应一个 SurfaceSession的。
3.Surface的传递
ViewRootImpl.setView
----->requestLayout
----->scheduleTraversals
----->sendEmptyMessage(DO_TRAVERSAL);
----->handleMessage()// 这里需要特别说以下,因为 ViewRootImpl是从Handler 派生的,所以在创建的时候,就与当前线程的 Looper绑定了,在投放消息后,会调用 Handler的handleMessage 进行处理
---->performTraversals
----->relayoutWindow
----->sWindowSession.relayout(mWindow, mSeq, params, (int) (mView.getMeasuredWidth() * appScale + 0.5f), (int) (mView.getMeasuredHeight() * appScale + 0.5f), viewVisibility, insetsPending, mWinFrame, mPendingContentInsets, mPendingVisibleInsets, mPendingConfiguration, mSurface);
这里的 sWindowSession.relayout实际上就是发起一次请求,需要特别注意两个参数,一个是第一个参数 mWindow,它是IWindow.Stub 类型,在服务器端收到这个请求后,就是根据这个参数来查找 WindowState对象的,另外一个参数,是最后一个参数 mSurface,它是Surface 类型,它在 JNI层会被绑定从服务器端传递的 SurfaceControl对象。
在IWindowSession中,我们可以看到这个客户端的请求,在服务器端的响应就是调用 Session.relayout
Session.relayout
----->WindowManagerService.relayoutWindow
----->Surface surface = win.createSurfaceLocked();// 该函数会在 WindowState对象中创建一个Surface对象
----->mSurface = new Surface( mSession.mSurfaceSession, mSession.mPid, mAttrs.getTitle().toString(), 0, w, h, format, flags);
----->outSurface.copyFrom(surface);
看到这里就涉及 Surface对象在进程间的传递了,在客户端这一侧, sWindowSession.relayout中的参数ViewRootImpl.mSurface 是在定义的时候就初始化了的
private final Surface mSurface = new Surface();
因为 sWindowSession是IWindowSession 类型,我们接着看它对应的 relayout函数
out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/android/view/IWindowSession.java
public int relayout(android.view.IWindow window, int seq, android.view.WindowManager.LayoutParams attrs, int requestedWidth, int requestedHeight, int viewVisibility, boolean insetsPending, android.graphics.Rect outFrame, android.graphics.Rect outContentInsets, android.graphics.Rect outVisibleInsets, android.content.res.Configuration outConfig, android.view.Surface outSurface) throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
int _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeStrongBinder((((window!=null))?(window.asBinder()):(null)));
_data.writeInt(seq);
if ((attrs!=null)) {
_data.writeInt(1);
attrs.writeToParcel(_data, 0);
}
else {
_data.writeInt(0);
}
_data.writeInt(requestedWidth);
_data.writeInt(requestedHeight);
_data.writeInt(viewVisibility);
_data.writeInt(((insetsPending)?(1):(0)));
mRemote.transact(Stub.TRANSACTION_relayout, _data, _reply, 0);//客户端发起relayout请求,并返回reply
_reply.readException();
_result = _reply.readInt();
if ((0!=_reply.readInt())) {
outFrame.readFromParcel(_reply);
}
if ((0!=_reply.readInt())) {
outContentInsets.readFromParcel(_reply);
}
if ((0!=_reply.readInt())) {
outVisibleInsets.readFromParcel(_reply);
}
if ((0!=_reply.readInt())) {
outConfig.readFromParcel(_reply);
}
if ((0!=_reply.readInt())) {
outSurface.readFromParcel(_reply);//从reply中读取outSurface
}
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
我们需要特别注意 mRemote.transact(Stub.TRANSACTION_relayout, _data, _reply, 0); 调用后返回的 _reply,outSurface.readFromParcel(_reply); 其中outSurface就是传递的最后一个参数,即 ViewRootImpl.mSurface。
在服务器端的 relayout过程中,也会创建Surface对象,它使用的是Surface的另外一个构造函数,它会调用 native函数init ,对应Surface_init函数
frameworks/base/core/jni/android_view_Surface.cpp
static void Surface_init(
JNIEnv* env, jobject clazz,
jobject session,
jint, jstring jname, jint dpy, jint w, jint h, jint format, jint flags)
(SurfaceComposerClient*)env->GetIntField(session, sso.client);
-----> SurfaceComposerClient* client =
(SurfaceComposerClient*)env->GetIntField(session, sso.client);
----->sp surface;
----->surface = client->createSurface(dpy, w, h, format, flags);
----->sp surface = mClient->createSurface(&data, name,display, w, h, format, flags);//
----->result = new SurfaceControl(this, surface, data);
----->setSurfaceControl(env, clazz, surface);
这里的参数 session对应着mSurface.mSurfaceSession 对象,在前面的分析中, WindowState.attach的时候创建了SurfaceSession对象,它也是进程唯一的,实际上它的构造函数中调用了 native函数init ,对应SurfaceSession_init函数,该函数也定义在 android_view_Surface.cpp中
static void SurfaceSession_init(JNIEnv* env, jobject clazz)
{
sp client = new SurfaceComposerClient;
client->incStrong(clazz);
env->SetIntField(clazz, sso.client, (int)client.get());
}
这里创建了一个 SurfaceComposerClient对象,并把这个对象与SurfaceSession对象绑定。在 Surface_init函数中,从SurfaceSession java 对象上获取的就是这个 client,SurfaceSession对象的职责就是把Session与Surface关联起来。这个client创建一个 surfacecontrol,并把它与Surface java 对象绑定 ,而这一切的动作都是在WindowManagerService所在进程进行的。所谓的 Surface.copyFrom实际上传递的就是与Surface对象绑定的 SurfaceControl native对象,在进程间传递的也是 SurfaceControl对象。
SurfaceControl native 对象中包含的最重要的就是 ISurface native实例,它被传递到客户端进程后,与 ViewRootImpl.mSurface java对象绑定,该对象是一个 Surface类型。
4.ISurface的创建
现在来看最重要的创建ISurface的过程,在上面的代码中 SurfaceComposerClient创建了ISurface 实例
mClient是SurfaceComposerClient 对象的成员变量,它是 sp类型的,它是在如下的代码中初始化的,也就是在 SurfaceComposerClient对象第一次被引用的时候
void SurfaceComposerClient::onFirstRef() {
sp sm(getComposerService());
if (sm != 0) {
sp conn = sm->createConnection();
if (conn != 0) {
mClient = conn;
mStatus = NO_ERROR;
}
}
}
其中 getComposerService()定义如下:
static inline sp getComposerService() {
return ComposerService::getComposerService();
}
sp ComposerService::getComposerService() {
return ComposerService::getInstance().mComposerService;
}
ComposerService的类定义如下:
class ComposerService : public Singleton
{
// these are constants
sp mComposerService;
sp mServerCblkMemory;
surface_flinger_cblk_t volatile* mServerCblk;
ComposerService();
friend class Singleton;
public:
static sp getComposerService();
static surface_flinger_cblk_t const volatile * getControlBlock();
};
它是一个单件,从 Singleton模板继承而来,只有一个实例,它的构造函数如下:
ComposerService::ComposerService()
: Singleton() {
const String16 name("SurfaceFlinger");
while (getService(name, &mComposerService) != NO_ERROR) {
usleep(250000);
}
mServerCblkMemory = mComposerService->getCblk();
mServerCblk = static_cast(
mServerCblkMemory->getBase());
}
其中 getService(name, &mComposerService)函数是定义在IServiceManager.h中的函数,功能是根据名称获取 Servcie的客户端,显然,这里是根据 SurfaceFlinger名称得到了该服务的客户端,其接口类型是 ISurfaceComposer,也就是说,上述createConnection函数,是客户端向服务器端发起的请求,显然返回的类型是一个 ISurfaceComposerClient类型,那么服务器端是如何处理的呢?首先,我们就要找到这个 Service
在init.rc中,启动了 surfaceflinger服务,
service surfaceflinger /system/bin/surfaceflinger
这个可执行文件是在 frameworks/base/cmds/surfaceflinger/main_surfaceflinger.cpp 编译出来的,该文件的内容非常简单,如下所示:
int main(int argc, char** argv) {
SurfaceFlinger::publishAndJoinThreadPool();
return 0;
}
我们来看 SurfaceFlinger类的定义
frameworks/base/services/surfaceflinger/SurfaceFlinger.h
class SurfaceFlinger :
public BinderService,
public BnSurfaceComposer,
public IBinder::DeathRecipient,
protected Thread
在它的基类 BinderService类中,定义了publishAndJoinThreadPool函数,它是一个模板类,该函数定义如下:
static void publishAndJoinThreadPool() {
sp proc(ProcessState::self());
sp sm(defaultServiceManager());
sm->addService(String16(SERVICE::getServiceName()), new SERVICE());
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
}
这与我们在前面分析 Binder的时候,添加服务的过程是相同的,同时,我们看到 SurfaceFlinger类也从是BnSurfaceComposer 继承的, BnSurfaceComposer是在frameworks/base/include/surfaceflinger/ISurfaceComposer.h 定义的,它从 BnInterface继承而来,也就是说SurfaceFlinger就是我们要找的服务器端类,
sp SurfaceFlinger::createConnection()
{
sp bclient;
sp client(new Client(this));
status_t err = client->initCheck();
if (err == NO_ERROR) {
bclient = client;
}
return bclient;
}
在上述代码中 Client的类型定义如下:
class Client : public BnSurfaceComposerClient ,也就是说,它也是一个服务器端类,它的 createSurface函数如下:
sp Client::createSurface(
ISurfaceComposerClient::surface_data_t* params,
const String8& name,
DisplayID display, uint32_t w, uint32_t h, PixelFormat format,
uint32_t flags)
{
/*
* createSurface must be called from the GL thread so that it can
* have access to the GL context.
*/
class MessageCreateSurface : public MessageBase {
sp result;
SurfaceFlinger* flinger;
ISurfaceComposerClient::surface_data_t* params;
Client* client;
const String8& name;
DisplayID display;
uint32_t w, h;
PixelFormat format;
uint32_t flags;
public:
MessageCreateSurface(SurfaceFlinger* flinger,
ISurfaceComposerClient::surface_data_t* params,
const String8& name, Client* client,
DisplayID display, uint32_t w, uint32_t h, PixelFormat format,
uint32_t flags)
: flinger(flinger), params(params), client(client), name(name),
display(display), w(w), h(h), format(format), flags(flags)
{
}
sp getResult() const { return result; }
virtual bool handler() {
result = flinger->createSurface(params, name, client,
display, w, h, format, flags);
return true;
}
};
sp msg = new MessageCreateSurface(mFlinger.get(),
params, name, this, display, w, h, format, flags);
mFlinger->postMessageSync(msg);
return static_cast( msg.get() )->getResult();
}
显然,上面的代码是创建一个消息,然后把它投放到一个消息队列中,其中关键的是 mFlinger->postMessageSync(msg),其代码如下:
status_t SurfaceFlinger::postMessageSync(const sp& msg,
nsecs_t reltime, uint32_t flags)
{
status_t res = mEventQueue.postMessage(msg, reltime, flags);
if (res == NO_ERROR) {
msg->wait();
}
return res;
}
也就是说, msg消息会被放入到EventQueue消息队列中,进行处理, msg->wait表示等待消息处理完成,这就说明问题了, postMessage所在的线程,与消息处理的线程必然是两个线程,那么这些线程又是如何创建的呢?
从前面创建 SurfaceFlinger服务的时候,我们知道SufaceFlinger的类继承结构, SurfaceFlinger继承自Thread ,看下面的代码
void SurfaceFlinger::onFirstRef()
{
run("SurfaceFlinger", PRIORITY_URGENT_DISPLAY);
// Wait for the main thread to be done with its initialization
mReadyToRunBarrier.wait();
}
我们从这里可以看到,它调用了 Thread.run函数,该函数会启动一个新的线程,在线程中将运行 threadLoop函数,mReadyToRunBarrier.wait(); 是为了等待线程启动起来,也就是说,在 init进程启动SurfaceFlinger 服务进程之后,创建 SurfaceFlinger实例,并在该实例第一次得到引用的时候,会启动一个新的线程,这个线程就是调用的就是 SurfaceFlinger.threadLoop函数,该函数代码如下:
bool SurfaceFlinger::threadLoop()
{
waitForEvent();
----->while(true)
----->sp msg = mEventQueue.waitMessage(timeout);
----->msg->handler()
----->msg->notify
。。。
}
注意,我们在 SurfaceFlinger::postMessageSync中,在把消息投入消息队列之后,调用了 msg->wait,也就是说该函数所在的线程被阻塞了,而上面的函数调用中, msg->notify显然是用来恢复这个阻塞的,这也就是 postMessageSync中Sync 的含义了。而在这里 handler的内容就是创建Surface
result = flinger->createSurface(params, name, client,display, w, h, format, flags);
该函数返回一个 ISurface的实例,并被保存在msg的 result变量中,最后返回给客户端进程,下面我们来看一下整体的创建流程
SurfaceFlinger service 的创建流程如下:
SystemServer进程创建WindowState 的过程如下:
SystemServer创建Surface 的过程如下:
SurfaceFlinger进程使用到的类关系如下:
SystemServer使用到的类关系如下:
ISurfaceComposer接口是SurfaceFlinger 提供的服务接口
ISurfaceComposerClient 是客户端进程与 SurfaceFlinger进程链接的通道,客户端进程并不直接使用 ISurfaceComposer接口,而是通过ISurfaceComposerClient接口,在服务器端进程调用 SurfaceFlinger实例的服务,由于ISurfaceComposerClient实例是保存在 SurfaceComposerClient中,它与SurfaceSession 是一一对应的,而 SurfaceSession与Session 又是一一对应的, Session在进程中是只有一个实例的,所以这个 ISurfaceComposerClient在进程中也是只有一个实例的。
SurfaceFlinger::createSurface
----->SurfaceFlinger::createSurface(
----->ssize_t token = addClientLayer(client, layer);
----->size_t name = client->attachLayer(lbc);
----->Client.mLayers.add(name,layer);
----->addLayer_l(lbc);
----->ssize_t i = mCurrentState.layersSortedByZ.add(layer);
----->surfaceHandle = layer->getSurface();
----->s = createSurface();
---->mClientSurfaceBinder = s->asBinder();
sp LayerBaseClient::createSurface()
{
class BSurface : public BnSurface, public LayerCleaner {
wp mOwner;
virtual sp getSurfaceTexture() const {
sp res;
sp that( mOwner.promote() );
if (that != NULL) {
res = that->mSurfaceTexture;
}
return res;
}
public:
BSurface(const sp& flinger,
const sp& layer)
: LayerCleaner(flinger, layer), mOwner(layer) { }
};
sp sur(new BSurface(mFlinger, this));
return sur;
}
从这里我们可以看到返回给客户端进程的 ISurface实例是如何创建的,同时, ISurface接口只有一个功能就是getSurfaceTexture,从这里也可以看到,它的作用就是返回这个 Layer的ISurefaceTexture 实例。另外,从上述过程中,我们可以看到在创建了 Surface之后,这个实例被保存在 layerbaseclient中。另外,LayerBaseClient 类本身就有 createSurface函数,如下:
sp LayerBaseClient::createSurface()
{
class BSurface : public BnSurface, public LayerCleaner {
virtual sp getSurfaceTexture() const { return 0; }
public:
BSurface(const sp& flinger,
const sp& layer)
: LayerCleaner(flinger, layer) { }
};
sp sur(new BSurface(mFlinger, this));
return sur;
}
从这里看到它的 getSufaceTexture方法返回的是0,这是什么意思呢? LayerBaseClient除了有Layer 这个派生类之外,还有 LayerDim,LayerScreenshot 派生类,他们都没有实现 createSurface方法,而是使用父类的函数,也就是说,只有创建了 Layer,才能得到ISurfaceTexture 接口,如果创建了其他两种 LayerBaseClient,则得不到这个接口。
上述过程可以用如下图表示:
我们以客户端进程 add一个View ,重新回顾整个创建过程,一个 View对应一个ViewRootImpl ,ViewRootImpl中有一个 IWindowSession接口实例,它是进程唯一的,通过它的 add方法,使WindowManagerService使用与这个 Session 绑定的ISurfaceComposerClient 接口向SurfaceFlinger 进程,来创建一个 ISurface接口,这个实例被保存在 SurfaceControl实例中,这个native层的实例与 java层的Surface 实例绑定到一起,并通过 IWindowSession接口传递给客户端进程。也就是说,一个 View对应了一个ISurface 接口,又对应一个 Layer,对应一个SurfaceTexture
三 .Surface的使用
上面我们看到了 ISurface接口是如何创建的,以及它是如何与 Surface java对象绑定到一起的,下面我们将要看到客户端进程是如何使用 Surface显示内容的。
我们从 Surface.lockCanvas看起
1.Surface.lockCanvas
从Surface.java中的 Surface.lockCanvas知道,它调用了native函数 lockCanvasNative函数,即frameworks/base/core/jni/android_view_Surface.cpp 文件中的 Surface_lockCanvas函数
static jobject Surface_lockCanvas(JNIEnv* env, jobject clazz, jobject dirtyRect)
{
const sp& surface(getSurface(env, clazz));
。。。。。。
Surface::SurfaceInfo info;
status_t err = surface->lock(&info, &dirtyRegion);
。。。。。。
SkCanvas* nativeCanvas = (SkCanvas*)env->GetIntField(canvas, no.native_canvas);
SkBitmap bitmap;
。。。。。。
if (info.w > 0 && info.h > 0) {
bitmap.setPixels(info.bits);
} else {
// be safe with an empty bitmap.
bitmap.setPixels(NULL);
}
nativeCanvas->setBitmapDevice(bitmap);
。。。。。。
return canvas;
}
这段代码的主要功能是使用 surface->lock得到SurfaceInfo ,然后把 info.bits设置给SkBitmap ,这个bitmap最后设置给 nativeCanvas,也就是说,在这个Canvas上画的数据都会被写道其中的 bitmap上,也就是info.bits 指定的地址上,这个地址上的数据就是显示数据。所以这段代码的关键是 Surface->lock函数。
2.Surface::lock
下面我们将从 Surface::lock开始,分析Surface 对象是如何与 SurfaceTexture通信的
frameworks/base/libs/gui/Surface.cpp
status_t Surface::lock(SurfaceInfo* other, Region* inOutDirtyRegion)
------>status_t err = SurfaceTextureClient::lock(&outBuffer, inOutDirtyBounds);
Surface继承自SurfaceTextureClient ,它直接调用了基类的 lock函数
status_t SurfaceTextureClient::lock(
ANativeWindow_Buffer* outBuffer, ARect* inOutDirtyBounds)
{
if (mLockedBuffer != 0) {
LOGE("Surface::lock failed, already locked");
return INVALID_OPERATION;
}
if (!mConnectedToCpu) {
int err = SurfaceTextureClient::connect(NATIVE_WINDOW_API_CPU);
----->int err = mSurfaceTexture->connect(api,&mDefaultWidth, &mDefaultHeight, &mTransformHint);//---------------
if (err) {
return err;
}
// we're intending to do software rendering from this point
setUsage(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN);
}
ANativeWindowBuffer* out;
status_t err = dequeueBuffer(&out);
------>status_t result = mSurfaceTexture->dequeueBuffer(&buf, mReqWidth, mReqHeight,mReqFormat, mReqUsage);--------------
LOGE_IF(err, "dequeueBuffer failed (%s)", strerror(-err));
if (err == NO_ERROR) {
sp backBuffer(GraphicBuffer::getSelf(out));
err = lockBuffer(backBuffer.get());
LOGE_IF(err, "lockBuffer (handle=%p) failed (%s)",
backBuffer->handle, strerror(-err));
if (err == NO_ERROR) {
const Rect bounds(backBuffer->width, backBuffer->height);
Region newDirtyRegion;
if (inOutDirtyBounds) {
newDirtyRegion.set(static_cast(*inOutDirtyBounds));
newDirtyRegion.andSelf(bounds);
} else {
newDirtyRegion.set(bounds);
}
// figure out if we can copy the frontbuffer back
const sp& frontBuffer(mPostedBuffer);
const bool canCopyBack = (frontBuffer != 0 &&
backBuffer->width == frontBuffer->width &&
backBuffer->height == frontBuffer->height &&
backBuffer->format == frontBuffer->format);
if (canCopyBack) {
// copy the area that is invalid and not repainted this round
const Region copyback(mOldDirtyRegion.subtract(newDirtyRegion));
if (!copyback.isEmpty())
copyBlt(backBuffer, frontBuffer, copyback);--------------
} else {
// if we can't copy-back anything, modify the user's dirty
// region to make sure they redraw the whole buffer
newDirtyRegion.set(bounds);
}
// keep track of the are of the buffer that is "clean"
// (ie: that will be redrawn)
mOldDirtyRegion = newDirtyRegion;
if (inOutDirtyBounds) {
*inOutDirtyBounds = newDirtyRegion.getBounds();
}
void* vaddr;
status_t res = backBuffer->lock(
GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,
newDirtyRegion.bounds(), &vaddr);--------------
LOGW_IF(res, "failed locking buffer (handle = %p)",
backBuffer->handle);
mLockedBuffer = backBuffer;
outBuffer->width = backBuffer->width;
outBuffer->height = backBuffer->height;
outBuffer->stride = backBuffer->stride;
outBuffer->format = backBuffer->format;
outBuffer->bits = vaddr;
}
}
return err;
}
下面依次对上面 4个函数进行分析
connect
这里显然是客户端发起请求,其中 api参数是NATIVE_WINDOW_API_CPU ,对应的,在 SurfaceTexture的connect ,实际上就是记录这个 api,并返回它保存的defaultWidth和 defaultHeight
dequeueBuffer
同样的是客户端发起请求,关键是看 SurfaceTexture::dequeueBuffer函数,该函数实际上就是在其成员变量 mSlots数组中查找一个合适的位置,并返回数组的序号,特别需要说明的是,如果这个合适位置的 buffer是经过重新分配得到的话,那么客户端还需要调用 requestBuffer方法才能重新得到新的GraphicBuffer。
copyBlt
先说明 frontBuffer和backBuffer ,这是两个逻辑概念,上次使用的 buffer被称为frontBuffer ,它保存在 mPostedbuffer,而现在将要使用的称为 backBuffer,在lock 之后,将使用 mLockedBuffer来保存它。在后面说明的 unlockAndPost函数之中,将把这个buffer变成 frontBuffer,即PostedBuffer 。
lock
status_t GraphicBuffer::lock(uint32_t usage, const Rect& rect, void** vaddr)
{
if (rect.left < 0 || rect.right > this->width ||
rect.top < 0 || rect.bottom > this->height) {
LOGE("locking pixels (%d,%d,%d,%d) outside of buffer (w=%d, h=%d)",
rect.left, rect.top, rect.right, rect.bottom,
this->width, this->height);
return BAD_VALUE;
}
status_t res = getBufferMapper().lock(handle, usage, rect, vaddr);
return res;
}
getBufferMapper()函数得到的是一个GraphicBufferMapper实例,实际上这个类是个单件,只有一个实例
status_t GraphicBufferMapper::lock(buffer_handle_t handle,
int usage, const Rect& bounds, void** vaddr)
{
status_t err;
err = mAllocMod->lock(mAllocMod, handle, usage,
bounds.left, bounds.top, bounds.width(), bounds.height(),
vaddr);
LOGW_IF(err, "lock(...) failed %d (%s)", err, strerror(-err));
return err;
}
其中 mAllocMod是在构造函数中得到的
GraphicBufferMapper::GraphicBufferMapper()
: mAllocMod(0)
{
hw_module_t const* module;
int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
LOGE_IF(err, "FATAL: can't find the %s module", GRALLOC_HARDWARE_MODULE_ID);
if (err == 0) {
mAllocMod = (gralloc_module_t const *)module;
}
}
该函数通过加载 gralloc.so得到hw_module_t ,也就是 gralloc_module_t,其定义如下:
hardware/libhardware/include/hardware/gralloc.h
/**
* Every hardware module must have a data structure named HAL_MODULE_INFO_SYM
* and the fields of this data structure must begin with hw_module_t
* followed by module specific information.
*/
typedef struct gralloc_module_t {
struct hw_module_t common;
int (*registerBuffer)(struct gralloc_module_t const* module,
buffer_handle_t handle);
int (*unregisterBuffer)(struct gralloc_module_t const* module,
buffer_handle_t handle);
int (*lock)(struct gralloc_module_t const* module,
buffer_handle_t handle, int usage,
int l, int t, int w, int h,
void** vaddr);
int (*unlock)(struct gralloc_module_t const* module,
buffer_handle_t handle);
void* reserved_proc[7];
} gralloc_module_t;
这里我们可以看到上面调用的 lock函数,显然GraphicBufferMapper 类是对这些方法的封装,在 GraphicBuffer类中使用了这些函数,那么这些函数的具体实现如何?他们的功能又是如何呢?这就要看看 gralloc模块的实现了。
3.Gralloc module
gralloc module涉及两个文件
hardware/libhardware/modules/gralloc/gralloc.cpp 中定义了服务器端用于分配内存的代码,
上图给出了 module和device 相关的结构之间的关系,他们的定义分别如下:
hardware/libhardware/modules/gralloc/gralloc_priv.h
struct private_module_t {
gralloc_module_t base;
private_handle_t* framebuffer;
uint32_t flags;
uint32_t numBuffers;
uint32_t bufferMask;
pthread_mutex_t lock;
buffer_handle_t currentBuffer;
int pmem_master;
void* pmem_master_base;
struct fb_var_screeninfo info;
struct fb_fix_screeninfo finfo;
float xdpi;
float ydpi;
float fps;
};
hardware/libhardware/include/hardware/hardware.h
/**
* Every hardware module must have a data structure named HAL_MODULE_INFO_SYM
* and the fields of this data structure must begin with hw_module_t
* followed by module specific information.
*/
typedef struct hw_module_t {
/** tag must be initialized to HARDWARE_MODULE_TAG */
uint32_t tag;
/** major version number for the module */
uint16_t version_major;
/** minor version number of the module */
uint16_t version_minor;
/** Identifier of module */
const char *id;
/** Name of this module */
const char *name;
/** Author/owner/implementor of the module */
const char *author;
/** Modules methods */
struct hw_module_methods_t* methods;
/** module's dso */
void* dso;
/** padding to 128 bytes, reserved for future use */
uint32_t reserved[32-7];
} hw_module_t;
hardware/libhardware/include/hardware/hardware.h
/**
* Every device data structure must begin with hw_device_t
* followed by module specific public methods and attributes.
*/
typedef struct hw_device_t {
/** tag must be initialized to HARDWARE_DEVICE_TAG */
uint32_t tag;
/** version number for hw_device_t */
uint32_t version;
/** reference to the module this device belongs to */
struct hw_module_t* module;
/** padding reserved for future use */
uint32_t reserved[12];
/** Close this device */
int (*close)(struct hw_device_t* device);
} hw_device_t;
/**
* Every device data structure must begin with hw_device_t
* followed by module specific public methods and attributes.
*/
typedef struct alloc_device_t {
struct hw_device_t common;
/*
* (*alloc)() Allocates a buffer in graphic memory with the requested
* parameters and returns a buffer_handle_t and the stride in pixels to
* allow the implementation to satisfy hardware constraints on the width
* of a pixmap (eg: it may have to be multiple of 8 pixels).
* The CALLER TAKES OWNERSHIP of the buffer_handle_t.
*
* Returns 0 on success or -errno on error.
*/
int (*alloc)(struct alloc_device_t* dev,
int w, int h, int format, int usage,
buffer_handle_t* handle, int* stride);
/*
* (*free)() Frees a previously allocated buffer.
* Behavior is undefined if the buffer is still mapped in any process,
* but shall not result in termination of the program or security breaches
* (allowing a process to get access to another process' buffers).
* THIS FUNCTION TAKES OWNERSHIP of the buffer_handle_t which becomes
* invalid after the call.
*
* Returns 0 on success or -errno on error.
*/
int (*free)(struct alloc_device_t* dev,
buffer_handle_t handle);
/* This hook is OPTIONAL.
*
* If non NULL it will be caused by SurfaceFlinger on dumpsys
*/
void (*dump)(struct alloc_device_t *dev, char *buff, int buff_len);
void* reserved_proc[7];
} alloc_device_t;
上面给出了图中列明的各种结构的定义,看起来挺复杂,让我们从 GraphicBufferMapper说起,它的构造函数中的 GRALLOC_HARDWARE_MODULE_ID就是"gralloc" 字符串,通过 hw_get_module函数,得到了hw_module_t结构,实际上它是一个 private_module结构,该结构都是以hw_module_t结构开始的,所以在上图中,我们把它们认为是继承关系,对于 gralloc模块来说,这个private_module定义如下:
hardware/libhardware/modules/gralloc/gralloc.cpp ,
struct private_module_t HAL_MODULE_INFO_SYM = {
base: {
common: {
tag: HARDWARE_MODULE_TAG,
version_major: 1,
version_minor: 0,
id: GRALLOC_HARDWARE_MODULE_ID,
name: "Graphics Memory Allocator Module",
author: "The Android Open Source Project",
methods: &gralloc_module_methods
},
registerBuffer: gralloc_register_buffer,
unregisterBuffer: gralloc_unregister_buffer,
lock: gralloc_lock,
unlock: gralloc_unlock,
},
framebuffer: 0,
flags: 0,
numBuffers: 0,
bufferMask: 0,
lock: PTHREAD_MUTEX_INITIALIZER,
currentBuffer: 0,
};
其中
static struct hw_module_methods_t gralloc_module_methods = {
open: gralloc_device_open
};
这里的 gralloc_register_buffer,gralloc_unregister_buffer,gralloc_lock,gralloc_unlock ,定义在 hardware/libhardware/modules/gralloc/mapper.cpp ,在GraphicBufferMapper中调用的 mAllocMod->lock就是这里的gralloc_lock 函数,其定义如下:
int gralloc_lock(gralloc_module_t const* module,
buffer_handle_t handle, int usage,
int l, int t, int w, int h,
void** vaddr)
{
// this is called when a buffer is being locked for software
// access. in thin implementation we have nothing to do since
// not synchronization with the h/w is needed.
// typically this is used to wait for the h/w to finish with
// this buffer if relevant. the data cache may need to be
// flushed or invalidated depending on the usage bits and the
// hardware.
if (private_handle_t::validate(handle) < 0)
return -EINVAL;
private_handle_t* hnd = (private_handle_t*)handle;
*vaddr = (void*)hnd->base;
return 0;
}
从这里我们看到,实际上只是取出了 handle中的一个地址,作为返回地址,这个地址的作用是什么,又是在哪里赋值的呢?首先,这个地址是从 handle中取出的,这个handle是从哪里来的呢?它是 GraphicBuffer调用lock 函数的时候,作为参数传递进来的,也就是说它是存储在 GraphicBuffer中的,那么GraphicBuffer 又是从何而来的呢?是从服务器端通过 Binder传递过来的,在GraphicBuffer中的 GraphicBuffer::unflatten函数中读取到的
status_t GraphicBuffer::unflatten(void const* buffer, size_t size,
int fds[], size_t count)
{
if (size < 8*sizeof(int)) return NO_MEMORY;
int const* buf = static_cast(buffer);
if (buf[0] != 'GBFR') return BAD_TYPE;
const size_t numFds = buf[6];
const size_t numInts = buf[7];
const size_t sizeNeeded = (8 + numInts) * sizeof(int);
if (size < sizeNeeded) return NO_MEMORY;
size_t fdCountNeeded = 0;
if (count < fdCountNeeded) return NO_MEMORY;
if (handle) {
// free previous handle if any
free_handle();
}
if (numFds || numInts) {
width = buf[1];
height = buf[2];
stride = buf[3];
format = buf[4];
usage = buf[5];
native_handle* h = native_handle_create(numFds, numInts);
memcpy(h->data, fds, numFds*sizeof(int));
memcpy(h->data + numFds, &buf[8], numInts*sizeof(int));
handle = h;
} else {
width = height = stride = format = usage = 0;
handle = NULL;
}
mOwner = ownHandle;
if (handle != 0) {
mBufferMapper.registerBuffer(handle);
}
return NO_ERROR;
}
要想读懂这段代码,首先要了解 native_handle的结构
system/core/include/cutils/native_handle.h
typedef struct native_handle
{
int version; /* sizeof(native_handle_t) */
int numFds; /* number of file-descriptors at &data[0] */
int numInts; /* number of ints at &data[numFds] */
int data[0]; /* numFds + numInts ints */
} native_handle_t;
system/core/include/system/window.h
typedef const native_handle_t* buffer_handle_t;
native_handle_t的data 字段,比较特别,它在 native_handle_t中并不占用内存,但是它指向 numInts后的内存,按照说明,numFds表示从 data[0]处开始,有几个fd, numInts表示从data[numFds] 开始有几个 int数据,总体的大小就是numFds+numInts个 int,实际上,data 是一个指向私有结构的指针,对于 gralloc来说,这个结构定义如下:
hardware/libhardware/modules/gralloc/gralloc_priv.h
struct private_handle_t {
struct native_handle nativeHandle;
enum {
PRIV_FLAGS_FRAMEBUFFER = 0x00000001
};
// file-descriptors
int fd;
// ints
int magic;
int flags;
int size;
int offset;
// FIXME: the attributes below should be out-of-line
int base;
int pid;
static const int sNumInts = 6;
static const int sNumFds = 1;
static const int sMagic = 0x3141592;
。。。
}
也就是说,在 native_handle之后,紧接着这样一个private_handel_t结构,在这里只有一个 fd,除此之外还有6个 int。这样我们就从服务器端跨进程,得到了 native_handle。
unflatten的最后动作是调用了registerBuffer ,这个函数实际上调用了 gralloc模块的registerBuffer 函数,即 gralloc_register函数,该函数定义如下:
int gralloc_register_buffer(gralloc_module_t const* module,
buffer_handle_t handle)
{
if (private_handle_t::validate(handle) < 0)
return -EINVAL;
// if this handle was created in this process, then we keep it as is.
int err = 0;
private_handle_t* hnd = (private_handle_t*)handle;
if (hnd->pid != getpid()) {
void *vaddr;
err = gralloc_map(module, handle, &vaddr);
}
return err;
}
其中调用的 gralloc_map函数定义如下:
static int gralloc_map(gralloc_module_t const* module,
buffer_handle_t handle,
void** vaddr)
{
private_handle_t* hnd = (private_handle_t*)handle;
if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) {
size_t size = hnd->size;
void* mappedAddress = mmap(0, size,
PROT_READ|PROT_WRITE, MAP_SHARED, hnd->fd, 0);
if (mappedAddress == MAP_FAILED) {
LOGE("Could not mmap %s", strerror(errno));
return -errno;
}
hnd->base = intptr_t(mappedAddress) + hnd->offset;
//LOGD("gralloc_map() succeeded fd=%d, off=%d, size=%d, vaddr=%p",
// hnd->fd, hnd->offset, hnd->size, mappedAddress);
}
*vaddr = (void*)hnd->base;
return 0;
}
看到这里,我们就明白了,原来所谓注册的动作,实际上是根据从 Binder传递过来的handle 中的size和 fd,做了一个内存映射的操作,并把系统返回的地址保存在 handle中,并作为返回值被返回出去。特别说明的是, fd之所以能够在进程间传递,也是因为在 Binder中对其进行了特殊处理,具体方法在前文中已经说明。
现在我们对客户端的 lock过程已经很清楚了,但是还有一个流程我们还不清楚,即服务器端是如何进行 GraphicBuffer的分配的呢?
在GraphicBuffer.cpp中,我们看到所谓 reallocate的过程,实际上是通过GraphicBufferAllocator进行真实的分配的, GraphicBuffer得到的只是一个handle,所以我们看看 GraphicBufferAllocator是如何完成分配动作的,先看看它的构造函数
GraphicBufferAllocator::GraphicBufferAllocator()
: mAllocDev(0)
{
hw_module_t const* module;
int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
LOGE_IF(err, "FATAL: can't find the %s module", GRALLOC_HARDWARE_MODULE_ID);
if (err == 0) {
gralloc_open(module, &mAllocDev);
}
}
其中的 gralloc_open的定义如下:
hardware/libhardware/include/hardware/gralloc.h
static inline int gralloc_open(const struct hw_module_t* module,
struct alloc_device_t** device) {
return module->methods->open(module,
GRALLOC_HARDWARE_GPU0, (struct hw_device_t**)device);
}
这里使用到了 module中method 的open函数,从上面 module的定义,我们知道这个open函数就是 gralloc_device_open
hardware/libhardware/modules/gralloc/gralloc.cpp
int gralloc_device_open(const hw_module_t* module, const char* name,
hw_device_t** device)
{
int status = -EINVAL;
if (!strcmp(name, GRALLOC_HARDWARE_GPU0)) {
gralloc_context_t *dev;
dev = (gralloc_context_t*)malloc(sizeof(*dev));
/* initialize our state here */
memset(dev, 0, sizeof(*dev));
/* initialize the procs */
dev->device.common.tag = HARDWARE_DEVICE_TAG;
dev->device.common.version = 0;
dev->device.common.module = const_cast(module);
dev->device.common.close = gralloc_close;
dev->device.alloc = gralloc_alloc;
dev->device.free = gralloc_free;
*device = &dev->device.common;
status = 0;
} else {
status = fb_device_open(module, name, device);
}
return status;
}
从这里我们知道,这个 device设备是通过module 打开的,这就是 module和device 之间的关系。在 GraphicBufferAllocator中调用的alloc 函数,就是 gralloc_alloc函数,
hardware/libhardware/modules/gralloc/gralloc.cpp
static int gralloc_alloc(alloc_device_t* dev,
int w, int h, int format, int usage,
buffer_handle_t* pHandle, int* pStride)
{
if (!pHandle || !pStride)
return -EINVAL;
size_t size, stride;
int align = 4;
int bpp = 0;
switch (format) {
case HAL_PIXEL_FORMAT_RGBA_8888:
case HAL_PIXEL_FORMAT_RGBX_8888:
case HAL_PIXEL_FORMAT_BGRA_8888:
bpp = 4;
break;
case HAL_PIXEL_FORMAT_RGB_888:
bpp = 3;
break;
case HAL_PIXEL_FORMAT_RGB_565:
case HAL_PIXEL_FORMAT_RGBA_5551:
case HAL_PIXEL_FORMAT_RGBA_4444:
bpp = 2;
break;
default:
return -EINVAL;
}
size_t bpr = (w*bpp + (align-1)) & ~(align-1);
size = bpr * h;
stride = bpr / bpp;
int err;
if (usage & GRALLOC_USAGE_HW_FB) {
err = gralloc_alloc_framebuffer(dev, size, usage, pHandle);
} else {
err = gralloc_alloc_buffer(dev, size, usage, pHandle);
}
if (err < 0) {
return err;
}
*pStride = stride;
return 0;
}
我们以软件分配为例,它将调用 gralloc_alloc_buffer
hardware/libhardware/modules/gralloc/gralloc.cpp
static int gralloc_alloc_buffer(alloc_device_t* dev,
size_t size, int usage, buffer_handle_t* pHandle)
{
int err = 0;
int fd = -1;
size = roundUpToPageSize(size);
fd = ashmem_create_region("gralloc-buffer", size);
if (fd < 0) {
LOGE("couldn't create ashmem (%s)", strerror(-errno));
err = -errno;
}
if (err == 0) {
private_handle_t* hnd = new private_handle_t(fd, size, 0);
gralloc_module_t* module = reinterpret_cast(
dev->common.module);
err = mapBuffer(module, hnd);
if (err == 0) {
*pHandle = hnd;
}
}
LOGE_IF(err, "gralloc failed err=%s", strerror(-err));
return err;
}
hardware/libhardware/modules/gralloc/mapper.cpp
int mapBuffer(gralloc_module_t const* module,
private_handle_t* hnd)
{
void* vaddr;
return gralloc_map(module, hnd, &vaddr);
}
ashmem_create_region 函数根据 size创建了匿名的共享内存块,以文件名 fd来标识,最后还是通过mapper.cpp中的 gralloc_map函数映射到内存中,其过程与客户端是一样的,这样,我们对整个的分配过程就很清晰了,其过程可描述如下:
至此,从ViewRootImpl.setView方法来看,该方法的作用就是把当前ViewRootImpl.IWindow加入到session中,在服务端WMS上创建对应的WindowState,然后通过SurfaceFlinger创建ISurface实例,并把它通过SurfaceControl与ViewRootImpl.mSurface绑定
4.Surface的使用
ViewRootImpl.draw函数对Surface的使用如下:
ViewRootImpl.draw(){
Surface surface = mSurface;
。。。
Canvas canvas = surface.lockCanvas(null);
。。。
mView.draw(canvas);
。。。
surface.unlockCanvasAndPost(canvas);
}
mSurface在setView的时候就被绑定了native ISurface实例,lockCanvas将得到一个分配了Asm内存的GraphicBuffer,这个buffer中的内存地址,设置给SkBitmap,这个bitmap又设置给canvas,后续的画图操作都在这个canvas上进行,unlockCanvasAndPost操作,将把GraphicBuffer在SurfaceFlinger服务端入队列,然后等待flip
总体来说,上面描述的类及其关系,即所在进程的关系如下:
本图中需要特别说明的是,Surface java对象,既与SurfaceControl绑定,又与Surface native对象绑定,他们是有不同的目的的。
在前面的分析中,我们知道addView的时候,最终得到的ISurface实例是存储在SurfaceControl中,SurfaceControl与ViewRootImpl中的Surface对象绑定的,也就是说android在绘制view这类控件的时候,是走的SurfaceControl这条路的
除此之外,android还提供了另外一条路,Surface native对象可以通过SurfaceControl对象来初始化,可以使用SurfaceTexture初始化,该native对象最后与Surface java对象绑定。
ViewRootImpl.draw(boolean fullRedrawNeeded) {
Surface surface = mSurface;
....
canvas = surface.lockCanvas(dirty);
....
mView.draw(canvas);
....
surface.unlockCanvasAndPost(canvas);
}