編輯:關於Android編程
本文均屬自己閱讀源碼的點滴總結,轉賬請注明出處謝謝。
歡迎和大家交流。qq:1037701636 email:[email protected]
Android源碼版本Version:4.2.2; 硬件平台 全志A31
step1.前面的幾張博文都在記錄SurfaceFLinger側,也就是所謂的Server端,接下去就和大家來看看客戶端是如何將要處理的圖形信息請求SF來傳遞出去的呢。大家學習的一個方式都是通過android啟動的第一個開機畫面來入手的,先來看看啟動的函數,再來看這個類BootAnimation。
int main(int argc, char** argv)//由surfaceflinger來觸發init進程來啟動它 { #if defined(HAVE_PTHREADS) setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_DISPLAY); #endif char value[PROPERTY_VALUE_MAX]; property_get("debug.sf.nobootanimation", value, "0"); int noBootAnimation = atoi(value); ALOGI_IF(noBootAnimation, "boot animation disabled"); if (!noBootAnimation) { spproc(ProcessState::self()); ProcessState::self()->startThreadPool();//這裡會進行binder的驅動初始化 // create the boot animation object sp boot = new BootAnimation();//初始化並會調用BootAnimation的onFirstRef,啟動一個線程 boot->playBootMusic("/system/media/boot.wav"); IPCThreadState::self()->joinThreadPool(); } return 0; }
我們會問Bootanimation是在哪裡啟動的呢,可以看我之前寫的文章android從init到開機動畫啟動關閉流程一簡易圖(surfaceflinger啟動的位置)裡面講到了SF啟動之後init主進程才有可能啟動它,因為bootanimation在init.rc是配置為disable,在SF裡面會出現的readyToRun函數內的startBootAnim();//開啟動畫屬性,通過設置內存屬性值來觸發Init進程來啟動:
void SurfaceFlinger::startBootAnim() { // start boot animation property_set("service.bootanim.exit", "0"); property_set("ctl.start", "bootanim"); }
在BootAnimation的main函數中,開始新建類的對象。
BootAnimation::BootAnimation() : Thread(false) { mSession = new SurfaceComposerClient();//SurfaceComposerClient,msession:sp}
可以想象的到,作為線程類Thread的派生類,明顯的很多事情是在thread的readyToRun和ThreadLoop裡面發生的,而新線程也一般就是在OnFirstRef中啟動run函數的。
在BootAnimation的構造函數中看到了一個SurfaceComposerClient類,理解為界面合成客戶端,的確BootAnimation將會作為一個客戶端請求SF去完成圖層的渲染。那麼SCC是如何和SF交互的呢,我們來看SCC的構造過程。
SurfaceComposerClient::SurfaceComposerClient() : mStatus(NO_INIT), mComposer(Composer::getInstance()) { } void SurfaceComposerClient::onFirstRef() { spsm(ComposerService::getComposerService());//獲得SurfaceFlinger的proxy BpSurfaceComposer if (sm != 0) { sp conn = sm->createConnection();//建立一個連接,獲得SurfaceFlinger遠程的客戶端BpSurfaceComposerClient,對應於服務端的Client if (conn != 0) { mClient = conn;//BpISurfaceComposerClient保存在mclient mStatus = NO_ERROR; } } }
在調用構造函數時初始化一個Composer類成員變量,且為單列模式。再來看onFirstRef中的操作,ComposerService::getComposerService:
spComposerService::getComposerService() { ComposerService& instance = ComposerService::getInstance();//ComposerService對象創建,單列模式BpSurfaceComposer,保存在其成員mComposerService Mutex::Autolock _l(instance.mLock); if (instance.mComposerService == NULL) { ComposerService::getInstance().connectLocked(); assert(instance.mComposerService != NULL); ALOGD("ComposerService reconnected"); } return instance.mComposerService;//成員代碼BpSurfaceComposer }
內部又出現一個ComposerService這個單列模式,看看他的構造函數:
ComposerService::ComposerService() : Singleton() { Mutex::Autolock _l(mLock); connectLocked(); }
果然會調用一個connectLocked函數:
void ComposerService::connectLocked() { const String16 name("SurfaceFlinger"); while (getService(name, &mComposerService) != NO_ERROR) {//返回surfaceflinger的代理到mComposerService usleep(250000); }
很清楚的是getService,可以想象的是應該是和ServiceManger在交互了,如下:
status_t getService(const String16& name, sp* outService) { const sp sm = defaultServiceManager(); if (sm != NULL) { *outService = interface_cast (sm->getService(name)); if ((*outService) != NULL) return NO_ERROR; } return NAME_NOT_FOUND; }
果然在這裡就是看到了通用的客戶端和SM的交互過程了,這裡就是實現了客戶端請求SM返回SurfaceFlinger的服務端在本地的代理proxy。最終保存到mCompserService變量中且該對象的類型為BpSurfaceComposer和SF(實際上SF繼承了BnSurfaceComposer這個本地對象)處建立起基於Binder的C/S通信架構。
好了上面的代碼執行了這麼多就是為了調用sm->createConnection()函數,這個就是典型的Binder通信方式了,可以看到:
virtual spcreateConnection() { uint32_t n; Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); remote()->transact(BnSurfaceComposer::CREATE_CONNECTION, data, &reply); return interface_cast (reply.readStrongBinder());//返回的Bpbinder轉為SurfaceComposerClient }
最終返回的是一個BpSurfaceComposerClient,當然核心的處理都是SF在建立的。那麼回到SurfaceFlinger裡面看看這個BpSurfaceComposerClient對象在SF裡的實際角色吧。
SF最終會調用createConnection()函數(這個過程分別經過了BnSurfaceComposer的onTransact處理,SF繼承了BnSurfaceComposer).
spSurfaceFlinger::createConnection() { sp bclient; sp client(new Client(this));//客戶端遠程調用時new一個BnSurfaceComposerClient status_t err = client->initCheck(); if (err == NO_ERROR) { bclient = client; } return bclient; }
可以看到這裡是調用了這個Client,而基於Binder通信架構的話這個Client肯定是繼承了BnSurfaceComposerClient,故BnSurfaceComposerClient在SF中其實是一個Client類,
status_t BnSurfaceComposer::onTransact(//內部函數由繼承類SF來完成 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { switch(code) { case CREATE_CONNECTION: { CHECK_INTERFACE(ISurfaceComposer, data, reply); spb = createConnection()->asBinder();//創建一個Bpbinder reply->writeStrongBinder(b);//返回給客戶端一個BpBinder的handle } break;
最終轉為Binder類型,寫入到Binder分配一個唯一的handle,最終寫回給BpSurfaceComposer客戶端供進一步的BpSurfaceComposerClient和Client之間的通信,而這個Client的代理最終保存在SurfaceComposerClient類對象的成員函數mClient中去。
step2.接著看Bootanimation裡的readyToRun(),內部有如下的一個函數即創建本地的Surface。
// create the native surface spcontrol = session()->createSurface(String8("BootAnimation"), dinfo.w, dinfo.h, PIXEL_FORMAT_RGB_565);//請求surfaceflinger來創建一個surface
session()函數返回之前創建的SurfaceComposerClient,上述函數實際實現如下:
spSurfaceComposerClient::createSurface( const String8& name, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags) { sp result; if (mStatus == NO_ERROR) { ISurfaceComposerClient::surface_data_t data; sp surface = mClient->createSurface(&data, name, w, h, format, flags);//對應的由SF側的錍lient來完成, BpSurface if (surface != 0) { result = new SurfaceControl(this, surface, data);//將得到的surface關聯到一個SurfaceControl } } return result; }
很顯然可以看到是有mClient來實現的,故在SF側就是由之前的new Client處創建的一個Client來完成這個交互的。故回到Client的onTransact函數中去
status_t Client::onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { ....return BnSurfaceComposerClient::onTransact(code, data, reply, flags);//內部就是調用繼承類Client的createSurface }
接著往下看:
status_t BnSurfaceComposerClient::onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { switch(code) { case CREATE_SURFACE: { CHECK_INTERFACE(ISurfaceComposerClient, data, reply); surface_data_t params; String8 name = data.readString8(); uint32_t w = data.readInt32(); uint32_t h = data.readInt32(); PixelFormat format = data.readInt32(); uint32_t flags = data.readInt32(); sps = createSurface(?ms, name, w, h, format, flags);//創建一個surface params.writeToParcel(reply); reply->writeStrongBinder(s->asBinder());//本地的BBinder寫入給客戶端 return NO_ERROR; } break;......
因為BnSurfaceComposerClient被Client繼承,故實際調用的還是Client的createrSurface()函數,相關的實現見下一博文SurfaceFlinger中Surface和Layer的建立。
我推薦的網站,都是我在學習Android 開發過程中發現的好網站,給初學者一些建議,少走一些彎路。Android Developers作為一個Android 開發者,官網
注冊很多app或者網絡賬戶的時候,經常需要手機獲取驗證碼,來完成注冊,那時年少,只是覺得手機獲取驗證碼這件事兒很好玩,並沒有關心太多,她是如何實現的,以及她背後的故事到底
一、背景Xposed,大名鼎鼎得Xposed,是Android平台上最負盛名的一個框架。在這個框架下,我們可以加載很多插件App,這些插件App可以直接或間接操縱系統層面
首先分析下游戲界面內的元素:無限滾動的背景圖, 可以操作的主角,主角的子彈, 主角的血量,兩種怪物(敵機),一個boss, boss的爆炸效果.先看效果圖1、首先實現無限