這篇文章主要描述從 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);
}