[TOC]
上層Client和SurfaceFlinger的交互
為了很好的切入主題滞谢,我們這里基于Native的Framework進行應(yīng)用的開發(fā)呢运吓,不是指的NDK應(yīng)用淀歇。我們直接用系統(tǒng)接口逼纸,進行開發(fā)歌亲。Native應(yīng)用直接拋棄掉Android的Java上層,AMS疾就,WMS澜术,View等,直接在Native開發(fā)猬腰,這樣便于我們理解顯示系統(tǒng)鸟废。
Native應(yīng)用建立
在顯示子系統(tǒng)中,Surface是一個很重要的類漆诽,通過Surface我們就能獲取到Buffer侮攀,我們就能夠和Android Native窗口系統(tǒng)建立連接锣枝。我們就基于Surface來寫一個Native的應(yīng)用厢拭。
首先,我們先定義一個封裝類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對應(yīng)的實現(xiàn)如下:
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的窗口系統(tǒng)建立聯(lián)系陨闹,我們直接往這個窗口里面繪制我們需要的界面就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;
}
解釋一下代碼中的關(guān)鍵點:
- 創(chuàng)建一個SurfaceComposerClient,這是應(yīng)用端趋厉,是SurfaceFlinger的Client端寨闹,它將建立和SurfaceFlinger服務(wù)的通信
- getDisplayInfo,獲取手機屏幕的信息
- createSurface君账,創(chuàng)建SurfaceControl繁堡,在SurfaceFlinger創(chuàng)建對應(yīng)的Layer等~
- setLayer,設(shè)置窗口的z-Oder乡数,SurfaceFlinger根據(jù)z-Oder決定窗口的可見性及可見大小
- show椭蹄,讓當前窗口可見
- apply,這時净赴,上面的設(shè)置的屬性才真正生效绳矩,傳給SurfaceFlinger
至于怎么畫界面,我們接來下再介紹玖翅,稍后再給出drawNativeWindow的代碼翼馆。我們先來看割以,目前都干了什么。
應(yīng)用和SurfaceFlinger的鏈接建立
應(yīng)用和SurfaceFlinger是兩個不同的進程写妥,他們采用Binder通信拳球,應(yīng)用是Client端,SurfaceFlinger是服務(wù)端珍特。在Android中ProcessState是客戶端和服務(wù)端公共的部分祝峻,作為Binder通信的基礎(chǔ),ProcessState是一個singleton類扎筒,每個進程只有一個對象莱找,這個對象負責(zé)打開Binder驅(qū)動,建立線程池嗜桌,讓其進程里面的所有線程都能通過Binder通信奥溺。與之相關(guān)的是IPCThreadState,每個線程都有一個IPCThreadState實例登記在Linux線程的上下文附屬數(shù)據(jù)中骨宠,主要負責(zé)Binder的讀取浮定,寫入和請求處理框架。IPCThreadState在構(gòu)造的時候獲取進程的ProcessState并記錄在自己的成員變量mProcess中层亿,通過mProcess可以獲得Binder的句柄桦卒。
我們這里將不詳細的介紹Binder。有需求的可以提匿又,我們開一個專題方灾。
SurfaceComposerClient的 定義非常簡單,繼承RefBase~碌更,這樣我們就可以直接用智能指針sp裕偿,wp管理SurfaceComposerClient對象,不用擔心SurfaceComposerClient對象的回收問題痛单。
智能指針sp嘿棘,wp,我們這里也不做詳細的介紹旭绒,有需求的可以提鸟妙,我們開一個專題。
在SurfaceComposerClient的構(gòu)造函數(shù)中快压,只初始化了一個裝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在構(gòu)建時,創(chuàng)建鏈接:
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服務(wù)還沒有啟動,等待250000后再查詢沪曙,知道等到SurffaceFlinger進程啟動奕污。DeathObserver是監(jiān)聽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函數(shù),將建立和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的實現(xiàn)為:
* 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端。
我們來看一下顶燕,顯示系統(tǒng)中凑保,Client和SurfaceFlinger的關(guān)系:
應(yīng)用端SurfaceComposerClient通過接口ISurfaceComposerClient和SurfaceFlinger的Client建立聯(lián)系。應(yīng)用端通過的ComposerService通過ISurfaceComposer和SurfaceFlinger建立聯(lián)系涌攻。
SurfaceFlinger的啟動
SurfaceFlinger是一個系統(tǒng)級的服務(wù)欧引,Android系統(tǒng)啟動的過程中就會啟動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
既然是獨立的進程维咸,系統(tǒng)級的服務(wù)剂买,那就有自己的main函數(shù):
* 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()->setThreadPoolMaxThreadCount(4);
// start the thread pool
sp<ProcessState> ps(ProcessState::self());
ps->startThreadPool();
// instantiate surfaceflinger
sp<SurfaceFlinger> flinger = new SurfaceFlinger();
setpriority(PRIO_PROCESS, 0, PRIORITY_URGENT_DISPLAY);
set_sched_policy(0, SP_FOREGROUND);
// Put most SurfaceFlinger threads in the system-background cpuset
// Keeps us from unnecessarily using big cores
// Do this after the binder thread pool init
if (cpusets_enabled()) set_cpuset_policy(0, SP_SYSTEM);
// initialize before clients can connect
flinger->init();
// publish surface flinger
sp<IServiceManager> sm(defaultServiceManager());
sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false,
IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL);
// publish GpuService
sp<GpuService> gpuservice = new GpuService();
sm->addService(String16(GpuService::SERVICE_NAME), gpuservice, false);
struct sched_param param = {0};
param.sched_priority = 2;
if (sched_setscheduler(0, SCHED_FIFO, ¶m) != 0) {
ALOGE("Couldn't set SCHED_FIFO");
}
// run surface flinger in this thread
flinger->run();
return 0;
}
SurfacFlinger進程中主要4個服務(wù):
- startHidlServices主要是啟動allocator
- DisplayService惠爽,主要負責(zé)DisplayEvent的處理
- SurfaceFlinger,主要顯示相關(guān)的瞬哼,最重要的服務(wù)
- GpuService婚肆,GPU相關(guān)的服務(wù),為訪問GPU
SurfaceFlinger類定義如下:
* frameworks/native/services/surfaceflinger/SurfaceFlinger.h
class SurfaceFlinger : public BnSurfaceComposer,
public PriorityDumper,
private IBinder::DeathRecipient,
private HWC2::ComposerCallback
SurfaceComposer是ISurfaceComposer的Bn端坐慰。實現(xiàn)了HWC2的ComposerCallback回調(diào)较性。死亡回收DeathRecipient,以及Dump信息PriorityDumper结胀。
構(gòu)造函數(shù)如下:
* frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
SurfaceFlinger::SurfaceFlinger()
: BnSurfaceComposer(),
mTransactionFlags(0),
mTransactionPending(false),
mAnimTransactionPending(false),
mLayersRemoved(false),
mLayersAdded(false),
mRepaintEverything(0),
mBootTime(systemTime()),
mBuiltinDisplays(),
mVisibleRegionsDirty(false),
mGeometryInvalid(false),
mAnimCompositionPending(false),
mDebugRegion(0),
mDebugDDMS(0),
mDebugDisableHWC(0),
mDebugDisableTransformHint(0),
mDebugInSwapBuffers(0),
mLastSwapBufferTime(0),
mDebugInTransaction(0),
mLastTransactionTime(0),
mBootFinished(false),
mForceFullDamage(false),
mInterceptor(this),
mPrimaryDispSync("PrimaryDispSync"),
mPrimaryHWVsyncEnabled(false),
mHWVsyncAvailable(false),
mHasColorMatrix(false),
mHasPoweredOff(false),
mNumLayers(0),
mVrFlingerRequestsDisplay(false),
mMainThreadId(std::this_thread::get_id())
{
ALOGI("SurfaceFlinger is starting");
vsyncPhaseOffsetNs = getInt64< ISurfaceFlingerConfigs,
&ISurfaceFlingerConfigs::vsyncEventPhaseOffsetNs>(1000000);
... ...
mPrimaryDispSync.init(SurfaceFlinger::hasSyncFramework, SurfaceFlinger::dispSyncPresentTimeOffset);
// debugging stuff...
char value[PROPERTY_VALUE_MAX];
... ...
property_get("ro.sf.disable_triple_buffer", value, "1");
mLayerTripleBufferingDisabled = atoi(value);
ALOGI_IF(mLayerTripleBufferingDisabled, "Disabling Triple Buffering");
... ...
}
在構(gòu)造函數(shù)中赞咙,主要是做初始化。從Android O開始糟港,vendor的一些配置攀操,都采用configstore的方式提供,就是這里的ISurfaceFlingerConfigs秸抚,這是一個系統(tǒng)服務(wù)速和。對應(yīng)的接口在 hardware/interfaces/configstore/ 歹垫。當然,采用屬性進行設(shè)置颠放,但是屬性設(shè)置的是debug的參數(shù)居多排惨。
SurfaceFlinger真正的初始化,是在init函數(shù)中:
void SurfaceFlinger::init() {
... ...
Mutex::Autolock _l(mStateLock);
// start the EventThread
sp<VSyncSource> vsyncSrc =
new DispSyncSource(&mPrimaryDispSync, SurfaceFlinger::vsyncPhaseOffsetNs, true, "app");
mEventThread = new EventThread(vsyncSrc, *this, false);
sp<VSyncSource> sfVsyncSrc =
new DispSyncSource(&mPrimaryDispSync, SurfaceFlinger::sfVsyncPhaseOffsetNs, true, "sf");
mSFEventThread = new EventThread(sfVsyncSrc, *this, true);
mEventQueue.setEventThread(mSFEventThread);
// set EventThread and SFEventThread to SCHED_FIFO to minimize jitter
struct sched_param param = {0};
param.sched_priority = 2;
if (sched_setscheduler(mSFEventThread->getTid(), SCHED_FIFO, ¶m) != 0) {
ALOGE("Couldn't set SCHED_FIFO for SFEventThread");
}
if (sched_setscheduler(mEventThread->getTid(), SCHED_FIFO, ¶m) != 0) {
ALOGE("Couldn't set SCHED_FIFO for EventThread");
}
// Get a RenderEngine for the given display / config (can't fail)
getBE().mRenderEngine = RenderEngine::create(HAL_PIXEL_FORMAT_RGBA_8888,
hasWideColorDisplay ? RenderEngine::WIDE_COLOR_SUPPORT : 0);
LOG_ALWAYS_FATAL_IF(getBE().mRenderEngine == nullptr, "couldn't create RenderEngine");
LOG_ALWAYS_FATAL_IF(mVrFlingerRequestsDisplay,
"Starting with vr flinger active is not currently supported.");
getBE().mHwc.reset(new HWComposer(getBE().mHwcServiceName));
getBE().mHwc->registerCallback(this, getBE().mComposerSequenceId);
if (useVrFlinger) {
auto vrFlingerRequestDisplayCallback = [this] (bool requestDisplay) {
// This callback is called from the vr flinger dispatch thread. We
// need to call signalTransaction(), which requires holding
// mStateLock when we're not on the main thread. Acquiring
// mStateLock from the vr flinger dispatch thread might trigger a
// deadlock in surface flinger (see b/66916578), so post a message
// to be handled on the main thread instead.
sp<LambdaMessage> message = new LambdaMessage([=]() {
ALOGI("VR request display mode: requestDisplay=%d", requestDisplay);
mVrFlingerRequestsDisplay = requestDisplay;
signalTransaction();
});
postMessageAsync(message);
};
mVrFlinger = dvr::VrFlinger::Create(getBE().mHwc->getComposer(),
getBE().mHwc->getHwcDisplayId(HWC_DISPLAY_PRIMARY).value_or(0),
vrFlingerRequestDisplayCallback);
if (!mVrFlinger) {
ALOGE("Failed to start vrflinger");
}
}
mEventControlThread = new EventControlThread(this);
mEventControlThread->run("EventControl", PRIORITY_URGENT_DISPLAY);
// initialize our drawing state
mDrawingState = mCurrentState;
// set initial conditions (e.g. unblank default device)
initializeDisplays();
getBE().mRenderEngine->primeCache();
// Inform native graphics APIs whether the present timestamp is supported:
if (getHwComposer().hasCapability(
HWC2::Capability::PresentFenceIsNotReliable)) {
mStartPropertySetThread = new StartPropertySetThread(false);
} else {
mStartPropertySetThread = new StartPropertySetThread(true);
}
if (mStartPropertySetThread->Start() != NO_ERROR) {
ALOGE("Run StartPropertySetThread failed!");
}
ALOGV("Done initializing");
}
在init函數(shù)中碰凶,主要做了一下幾件事:
- 創(chuàng)建兩個EventThread及其DispSyncSource暮芭,主要是用以處理和分發(fā)如Vsync;App和SurfaceFlinger的如Vsync是分開的欲低,不是同一個谴麦。
- 創(chuàng)建了自己的消息隊列mEventQueue,SurfaceFlinger的消息隊列
- 初始化了Client合成模式(GPU)合成時伸头,需要用到的RenderEngine
- 初始化HWComposer,注冊回調(diào)接口registerCallback恤磷,HAL會回調(diào)一些方法。
- 如果是VR模式魔策,創(chuàng)建mVrFlinger
- 創(chuàng)建mEventControlThread闯袒,處理Event事件,如Vsync事件和hotplug事件游岳。
- 初始化顯示設(shè)備initializeDisplays
SurfaceFlinger第一次引用時政敢,啟動mEventQueue消息隊列
void SurfaceFlinger::onFirstRef()
{
mEventQueue.init(this);
}
SurfaceFlinger這邊后續(xù)再繼續(xù),先回到Native應(yīng)用的創(chuàng)建
獲取Display信息
Android支持多給屏幕胚迫,多個屏幕可以顯示一樣的內(nèi)容喷户,也可以顯示不一樣的內(nèi)容。我們通常的把他們稱為主顯访锻,外顯和虛顯褪尝。主顯就是內(nèi)置的,默認的手機屏幕期犬;外顯就是HDMI河哑,MHL等連接的屏幕;虛顯龟虎,就是虛擬顯示器璃谨,通過WFD連接的屏幕,或者是類似屏幕一樣的Buffer消費者遣总。
屏幕都是通過ID來標記的:
* frameworks/native/services/surfaceflinger/DisplayDevice.h
enum DisplayType {
DISPLAY_ID_INVALID = -1,
DISPLAY_PRIMARY = HWC_DISPLAY_PRIMARY, //主顯
DISPLAY_EXTERNAL = HWC_DISPLAY_EXTERNAL, //外顯
DISPLAY_VIRTUAL = HWC_DISPLAY_VIRTUAL, //虛顯4
NUM_BUILTIN_DISPLAY_TYPES = HWC_NUM_PHYSICAL_DISPLAY_TYPES,
};
通過getBuiltInDisplay睬罗,去獲取指定ID的屏幕轨功。
sp<IBinder> SurfaceComposerClient::getBuiltInDisplay(int32_t id) {
return ComposerService::getComposerService()->getBuiltInDisplay(id);
}
getBuiltInDisplay是一個Binder調(diào)用,中間的Binder就省掉了古涧,直接看實現(xiàn):
sp<IBinder> SurfaceFlinger::getBuiltInDisplay(int32_t id) {
if (uint32_t(id) >= DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES) {
ALOGE("getDefaultDisplay: id=%d is not a valid default display id", id);
return NULL;
}
return mBuiltinDisplays[id];
}
前面初始化的時候算芯,屏幕都是采用熱插拔的形式上報职祷。內(nèi)置屏幕也是這樣。這個后續(xù)再介紹。
獲取屏幕后痰催,通過getDisplayInfo函數(shù),就能獲取屏幕的信息夹攒。
DisplayInfo mainDisplayInfo;
err = SurfaceComposerClient::getDisplayInfo(mainDisplay, &mainDisplayInfo);
if (err != NO_ERROR) {
fprintf(stderr, "ERROR: unable to get display characteristics\n");
return;
}
一個屏幕可以有多個config信息,當前再用的是activeconfig编检。在SurfaceComposerClient中,獲取config信息時蕾总,先獲取多有的config信息递雀,再獲取active的config的ID,根據(jù)ID去取Display信息杨凑。
status_t SurfaceComposerClient::getDisplayInfo(const sp<IBinder>& display,
DisplayInfo* info) {
Vector<DisplayInfo> configs;
status_t result = getDisplayConfigs(display, &configs);
if (result != NO_ERROR) {
return result;
}
int activeId = getActiveConfig(display);
if (activeId < 0) {
ALOGE("No active configuration found");
return NAME_NOT_FOUND;
}
*info = configs[static_cast<size_t>(activeId)];
return NO_ERROR;
}
getDisplayConfigs還是通過ComposerService去獲取的绅你,走的ISurfaceComposer的接口曼追。
status_t SurfaceComposerClient::getDisplayConfigs(
const sp<IBinder>& display, Vector<DisplayInfo>* configs)
{
return ComposerService::getComposerService()->getDisplayConfigs(display, configs);
}
在看SurfaceFlinger中g(shù)etDisplayConfigs的實現(xiàn)之前针史。我們先來看DisplayInfo的定義婚陪,看看Display信息都包含哪些」烈唬看看怎么來描述一個顯示屏幕。
struct DisplayInfo {
uint32_t w{0}; // 屏幕的寬
uint32_t h{0}; // 屏幕的高
float xdpi{0}; // 屏幕的x方向每英寸的像素點
float ydpi{0}; // 屏幕y方向每英寸的像素點
float fps{0}; // FPS屏幕的刷新率
float density{0}; // 屏幕的密度
uint8_t orientation{0}; // 屏幕的旋轉(zhuǎn)方式
bool secure{false}; // 屏幕是否是安全的
nsecs_t appVsyncOffset{0}; // App的Vsync的偏移
nsecs_t presentationDeadline{0}; // 顯示的最后時間
};
我們結(jié)合SurfaceFlinger中g(shù)etDisplayConfigs的實現(xiàn)蝇庭,來說說Display的信息病曾。
- 首先鲫竞,根據(jù)Display的IBinder从绘,找到Display的類型type。
* frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
status_t SurfaceFlinger::getDisplayConfigs(const sp<IBinder>& display,
Vector<DisplayInfo>* configs) {
... ...
int32_t type = NAME_NOT_FOUND;
for (int i=0 ; i<DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES ; i++) {
if (display == mBuiltinDisplays[i]) {
type = i;
break;
}
}
- 在根據(jù)type去獲取驅(qū)動中配置的信息getConfigs,getHwComposer().getConfigs(type);
ConditionalLock _l(mStateLock,
std::this_thread::get_id() != mMainThreadId);
for (const auto& hwConfig : getHwComposer().getConfigs(type)) {
- 最后合呐,根據(jù)驅(qū)動給的配置猖腕,和一些設(shè)置缘屹,構(gòu)建完整的顯示屏信息逻炊,下面是關(guān)鍵信息,刪掉了一些log和注解。
for (const auto& hwConfig : getHwComposer().getConfigs(type)) {
DisplayInfo info = DisplayInfo();
float xdpi = hwConfig->getDpiX();
float ydpi = hwConfig->getDpiY();
if (type == DisplayDevice::DISPLAY_PRIMARY) {
float density = Density::getBuildDensity() / 160.0f;
if (density == 0) {
density = xdpi / 160.0f;
}
if (Density::getEmuDensity()) {
xdpi = ydpi = density = Density::getEmuDensity();
density /= 160.0f;
}
info.density = density;
sp<const DisplayDevice> hw(getDefaultDisplayDeviceLocked());
info.orientation = hw->getOrientation();
} else {
static const int TV_DENSITY = 213;
info.density = TV_DENSITY / 160.0f;
info.orientation = 0;
}
info.w = hwConfig->getWidth();
info.h = hwConfig->getHeight();
info.xdpi = xdpi;
info.ydpi = ydpi;
info.fps = 1e9 / hwConfig->getVsyncPeriod();
info.appVsyncOffset = vsyncPhaseOffsetNs;
... ...
info.presentationDeadline = hwConfig->getVsyncPeriod() -
sfVsyncPhaseOffsetNs + 1000000;
// All non-virtual displays are currently considered secure.
info.secure = true;
configs->push_back(info);
}
return NO_ERROR;
}
屏幕信息:
-
屏幕寬高(W*H)
屏幕的寬高是用分辨率來描述的,也就是像素點的多少留美。像素是指在由一個數(shù)字序列表示的圖像中的一個最小單位捧颅,稱為像素症歇。屏幕多寬激捏,就是指闰蛔,屏幕橫向可以顯示多少個像素點蚤吹。屏幕多高就是指拱她,屏幕縱向可以顯示多少給像素點扔罪。平常所說的720P屏幕秉沼,就是1080x720,橫向可以顯示1080個像素點矿酵,縱向可以顯示720個像素點唬复。
此圖是,平常什么所說的一些分辨率:
每英寸的點數(shù)xdpi全肮,ydpi
顯示屏幕的物理大小壤巷,用英寸來描述,描述屏幕對角線的長度。比如iPhoneX 5.8英寸镊掖,指的是對角線的長度5.8英寸苟翻。而dpi,即Dots Per Inch瞻凤,表示每英寸有多少給點炕吸。百度百科的解釋為劣像,dpi是一個量度單位,用于點陣數(shù)碼影像,指每一英寸長度中,取樣、可顯示或輸出點的數(shù)目骑冗。
PPI(pixels per inch)和DPI是措辭的差別闷供,很多時候,都是混用的识藤。如iPhoneX是458 ppi;榮耀V9的DPI為488左右。density密度
這里的desity是一個縮放因子私痹,是 DPI / (160像素/英寸) 后得到的值,是一個比例值稠炬。
這可以看DisplayMetrics中關(guān)于density的定義:
frameworks/base/core/java/android/util/DisplayMetrics.java
/**
* The logical density of the display. This is a scaling factor for the
* Density Independent Pixel unit, where one DIP is one pixel on an
* approximately 160 dpi screen (for example a 240x320, 1.5"x2" screen),
* providing the baseline of the system's display. Thus on a 160dpi screen
* this density value will be 1; on a 120 dpi screen it would be .75; etc.
*
* <p>This value does not exactly follow the real screen size (as given by
* {@link #xdpi} and {@link #ydpi}, but rather is used to scale the size of
* the overall UI in steps based on gross changes in the display dpi. For
* example, a 240x320 screen will have a density of 1 even if its width is
* 1.8", 1.3", etc. However, if the screen resolution is increased to
* 320x480 but the screen size remained 1.5"x2" then the density would be
* increased (probably to 1.5).
*
* @see #DENSITY_DEFAULT
*/
public float density;
以設(shè)備無關(guān)像素DIP(device independent pixels)在160dpi屏幕上顯示為基礎(chǔ)焕阿。160dip在160dpi的屏幕上,density就是1酸纲,在120dpi的屏幕上捣鲸,density就為0.75。
屏幕刷新率FPS
FPS(Frame per second)闽坡,幀每秒栽惶。表示屏幕一描述,可以顯示多少幀圖像數(shù)據(jù)疾嗅。目前多少的手機顯示屏還是60FPS外厂,顯示一幀16.67ms左右。orientation屏幕旋轉(zhuǎn)方向
手機默認豎屏代承,0度豎屏汁蝶。
/* Display orientations as defined in Surface.java and ISurfaceComposer.h. */
enum {
DISPLAY_ORIENTATION_0 = 0,
DISPLAY_ORIENTATION_90 = 1,
DISPLAY_ORIENTATION_180 = 2,
DISPLAY_ORIENTATION_270 = 3
};
- 屏幕是否安全secure
這主要是用于DRM(數(shù)字版權(quán)保護)時,確保顯示的設(shè)備是安全的,以防止DRM的內(nèi)容被在顯示的過程中被截取掖棉。只有安全的設(shè)備才能顯示DRM的內(nèi)容墓律。
Android默認,所有的非虛擬顯示都是安全的幔亥。
// All non-virtual displays are currently considered secure.
info.secure = true;
- appVsyncOffset和presentationDeadline
這兩個都和 Vsync有關(guān)耻讽,后續(xù)會再介紹。appVsyncOffset是一個偏移量帕棉,在系統(tǒng)(或硬件Vsync)的基礎(chǔ)上做一些偏移针肥。presentationDeadline表示,一幀數(shù)據(jù)香伴,多就內(nèi)慰枕,必現(xiàn)要顯示出來。
Ok~到此即纲,SurfaceComposerClient端就拿到了多個config信息了具帮,在configs中。
Active config崇裁,就是當前被激活使用的:
int SurfaceFlinger::getActiveConfig(const sp<IBinder>& display) {
if (display == NULL) {
ALOGE("%s : display is NULL", __func__);
return BAD_VALUE;
}
sp<const DisplayDevice> device(getDisplayDevice(display));
if (device != NULL) {
return device->getActiveConfig();
}
return BAD_VALUE;
}
SurfaceFlinger服務(wù)中匕坯,Display的描述,用的DisplayDevice拔稳。每添加一個顯示屏,都會創(chuàng)建一個DisplayDevice锹雏。
int DisplayDevice::getActiveConfig() const {
return mActiveConfig;
}
activeconfig巴比,是一個索引值,對應(yīng)驅(qū)動中礁遵,對應(yīng)的config的索引轻绞。一般來說,active的config佣耐,都是默認的0政勃。當然SurfaceFlinger或上層是可以去設(shè)置的。
void DisplayDevice::setActiveConfig(int mode) {
mActiveConfig = mode;
}
回到應(yīng)用~
Native創(chuàng)建圖層Layer
拿到顯示信息后兼砖,根據(jù)轉(zhuǎn)屏奸远,這邊的尺寸需要做一下交換。因為不關(guān)屏幕怎么旋轉(zhuǎn)讽挟,我們需要顯示的內(nèi)容大小是沒有變的懒叛。
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;
}
接下里,就可以創(chuàng)建圖層了耽梅。
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;
}
createSurface函數(shù)如下:
sp<SurfaceControl> SurfaceComposerClient::createSurface(
const String8& name,
uint32_t w,
uint32_t h,
PixelFormat format,
uint32_t flags,
SurfaceControl* parent,
uint32_t windowType,
uint32_t ownerUid)
{
sp<SurfaceControl> sur;
if (mStatus == NO_ERROR) {
sp<IBinder> handle;
sp<IBinder> parentHandle;
sp<IGraphicBufferProducer> gbp;
if (parent != nullptr) {
parentHandle = parent->getHandle();
}
status_t err = mClient->createSurface(name, w, h, format, flags, parentHandle,
windowType, ownerUid, &handle, &gbp);
ALOGE_IF(err, "SurfaceComposerClient::createSurface error %s", strerror(-err));
if (err == NO_ERROR) {
sur = new SurfaceControl(this, handle, gbp);
}
}
return sur;
}
先解釋一下薛窥,其中的參數(shù):
name
name就是圖層的名字,沒有實際意義眼姐,主要是便于debug诅迷,有有名字佩番,就可以知道,我們創(chuàng)建的圖層是哪個了罢杉。w,h
這個是圖層的寬高答捕,我們用只是從DisplayInfo中讀出來的,跟屏幕的大小一樣屑那。format
圖層的格式拱镐,應(yīng)用中,我們用的格式是PIXEL_FORMAT_RGBX_8888持际。
我們通過RGB沃琅,紅,綠蜘欲,藍益眉,三原色可以調(diào)配所有的顏色。在數(shù)字世界里面姥份,也是用RGB來表示顏色郭脂,外加一個Alpha通道,就是RGBA澈歉。
RGBA_8888展鸡,表示R,G埃难,B莹弊,A分別用8bit表示。也就是說涡尘,R的取值范圍為0255忍弛。R從0255,表示最不紅到最紅考抄,值的大小细疚,表示紅的程度不同。
同樣川梅,Alpha A疯兼,也是表示透明的程度,RGBX中的X表示挑势,X為255镇防,不透明浊吏。
下面是Android中宿亡,常用的一些格式。
* frameworks/native/libs/ui/include/ui/PixelFormat.h
enum {
//
// these constants need to match those
// in graphics/PixelFormat.java & pixelflinger/format.h
//
PIXEL_FORMAT_UNKNOWN = 0,
PIXEL_FORMAT_NONE = 0,
// logical pixel formats used by the SurfaceFlinger -----------------------
PIXEL_FORMAT_CUSTOM = -4,
// Custom pixel-format described by a PixelFormatInfo structure
PIXEL_FORMAT_TRANSLUCENT = -3,
// System chooses a format that supports translucency (many alpha bits)
PIXEL_FORMAT_TRANSPARENT = -2,
// System chooses a format that supports transparency
// (at least 1 alpha bit)
PIXEL_FORMAT_OPAQUE = -1,
// System chooses an opaque format (no alpha bits required)
// real pixel formats supported for rendering -----------------------------
PIXEL_FORMAT_RGBA_8888 = HAL_PIXEL_FORMAT_RGBA_8888, // 4x8-bit RGBA
PIXEL_FORMAT_RGBX_8888 = HAL_PIXEL_FORMAT_RGBX_8888, // 4x8-bit RGB0
PIXEL_FORMAT_RGB_888 = HAL_PIXEL_FORMAT_RGB_888, // 3x8-bit RGB
PIXEL_FORMAT_RGB_565 = HAL_PIXEL_FORMAT_RGB_565, // 16-bit RGB
PIXEL_FORMAT_BGRA_8888 = HAL_PIXEL_FORMAT_BGRA_8888, // 4x8-bit BGRA
PIXEL_FORMAT_RGBA_5551 = 6, // 16-bit ARGB
PIXEL_FORMAT_RGBA_4444 = 7, // 16-bit ARGB
PIXEL_FORMAT_RGBA_FP16 = HAL_PIXEL_FORMAT_RGBA_FP16, // 64-bit RGBA
PIXEL_FORMAT_RGBA_1010102 = HAL_PIXEL_FORMAT_RGBA_1010102, // 32-bit RGBA
};
- flags
createSurface時巷蚪,可用的flag如下:
* frameworks/native/libs/gui/include/gui/ISurfaceComposerClient.h
// flags for createSurface()
enum { // (keep in sync with Surface.java)
eHidden = 0x00000004,
eDestroyBackbuffer = 0x00000020,
eSecure = 0x00000080,
eNonPremultiplied = 0x00000100,
eOpaque = 0x00000400,
eProtectedByApp = 0x00000800,
eProtectedByDRM = 0x00001000,
eCursorWindow = 0x00002000,
eFXSurfaceNormal = 0x00000000,
eFXSurfaceColor = 0x00020000,
eFXSurfaceMask = 0x000F0000,
};
Flag | 作用 | 說明 |
---|---|---|
eHidden | 隱藏 | 表示Layer是不可見的 |
eDestroyBackbuffer | 銷毀Back Buffer | 表示Layer不保存Back Buffer |
eSecure | 安全layer | 表示安全的Layer,只能顯示在Secure屏幕上 |
eNonPremultiplied | 非自左乘 | 針對Alpha通道的啦扬,如果沒有Alpha通道沒有實際意義 |
eOpaque | 非透明的 | 表示Layer不是透明的 |
eProtectedByApp | 應(yīng)用保護 | 應(yīng)用將請求一個安全的硬件通道傳輸?shù)酵怙@ |
eProtectedByDRM | DRM保護 | 應(yīng)用請求一個安全的通道傳輸DRM |
eCursorWindow | Cursor Layer | 其實這Layer就是鼠標一類的圖標 |
eFXSurfaceNormal | 普通的Layer | 系統(tǒng)中大多數(shù)layer都是此類 |
eFXSurfaceColor | 顏色layer | 在之前的版本中中狂,這個被稱為Dim Layer |
- windowType
窗口類型,可以參照WindowManager.java中的定義扑毡,如FIRST_SYSTEM_WINDOW胃榕,TYPE_STATUS_BAR等。默認值為0瞄摊。
- ownerUid
可以指定這個是哪個UID的Layer勋又。
繼續(xù)看createSurfface,Service端的實現(xiàn)如下:
status_t Client::createSurface(
const String8& name,
uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
const sp<IBinder>& parentHandle, uint32_t windowType, uint32_t ownerUid,
sp<IBinder>* handle,
sp<IGraphicBufferProducer>* gbp)
{
sp<Layer> parent = nullptr;
... ...
/*
* createSurface must be called from the GL thread so that it can
* have access to the GL context.
*/
class MessageCreateLayer : public MessageBase {
... ...
public:
MessageCreateLayer(SurfaceFlinger* flinger,
const String8& name, Client* client,
uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
sp<IBinder>* handle, uint32_t windowType, uint32_t ownerUid,
sp<IGraphicBufferProducer>* gbp,
sp<Layer>* parent)
: flinger(flinger), client(client),
handle(handle), gbp(gbp), result(NO_ERROR),
name(name), w(w), h(h), format(format), flags(flags),
parent(parent), windowType(windowType), ownerUid(ownerUid) {
}
status_t getResult() const { return result; }
virtual bool handler() {
result = flinger->createLayer(name, client, w, h, format, flags,
windowType, ownerUid, handle, gbp, parent);
return true;
}
};
sp<MessageBase> msg = new MessageCreateLayer(mFlinger.get(),
name, this, w, h, format, flags, handle,
windowType, ownerUid, gbp, &parent);
mFlinger->postMessageSync(msg);
return static_cast<MessageCreateLayer*>( msg.get() )->getResult();
}
Client類中换帜,創(chuàng)建Layer時楔壤,先找到parent Layer,對于我們的應(yīng)用來說惯驼,是沒有parent Layer的蹲嚣。然后再postMessageSync到SurfaceFlinger中,去創(chuàng)建祟牲,調(diào)用的SurfaceFlinger的createLayer方法隙畜。
SurfaceFlinger中,都是采用post Message的形式調(diào)到SurfaceFlinger的主線程中说贝。
status_t SurfaceFlinger::createLayer(
const String8& name,
const sp<Client>& client,
uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
uint32_t windowType, uint32_t ownerUid, sp<IBinder>* handle,
sp<IGraphicBufferProducer>* gbp, sp<Layer>* parent)
{
if (int32_t(w|h) < 0) {
ALOGE("createLayer() failed, w or h is negative (w=%d, h=%d)",
int(w), int(h));
return BAD_VALUE;
}
status_t result = NO_ERROR;
sp<Layer> layer;
String8 uniqueName = getUniqueLayerName(name);
switch (flags & ISurfaceComposerClient::eFXSurfaceMask) {
case ISurfaceComposerClient::eFXSurfaceNormal:
result = createBufferLayer(client,
uniqueName, w, h, flags, format,
handle, gbp, &layer);
break;
case ISurfaceComposerClient::eFXSurfaceColor:
result = createColorLayer(client,
uniqueName, w, h, flags,
handle, &layer);
break;
default:
result = BAD_VALUE;
break;
}
if (result != NO_ERROR) {
return result;
}
// window type is WINDOW_TYPE_DONT_SCREENSHOT from SurfaceControl.java
// TODO b/64227542
if (windowType == 441731) {
windowType = 2024; // TYPE_NAVIGATION_BAR_PANEL
layer->setPrimaryDisplayOnly();
}
layer->setInfo(windowType, ownerUid);
result = addClientLayer(client, *handle, *gbp, layer, *parent);
if (result != NO_ERROR) {
return result;
}
mInterceptor.saveSurfaceCreation(layer);
setTransactionFlags(eTransactionNeeded);
return result;
}
getUniqueLayerName议惰,確保Layer 的name沒有重名。
SurfaceFlinger中狂丝,主要處理兩中類似的Layer换淆,eFXSurfaceNormal和eFXSurfaceColor。兩種類似分別有createBufferLayer和createColorLayer兩個接口實現(xiàn)几颜。怎么創(chuàng)建的這里就不介紹了,后續(xù)再介紹讯屈。
addClientLayer做了什么:
status_t SurfaceFlinger::addClientLayer(const sp<Client>& client,
const sp<IBinder>& handle,
const sp<IGraphicBufferProducer>& gbc,
const sp<Layer>& lbc,
const sp<Layer>& parent)
{
// add this layer to the current state list
{
Mutex::Autolock _l(mStateLock);
if (mNumLayers >= MAX_LAYERS) {
ALOGE("AddClientLayer failed, mNumLayers (%zu) >= MAX_LAYERS (%zu)", mNumLayers,
MAX_LAYERS);
return NO_MEMORY;
}
if (parent == nullptr) {
mCurrentState.layersSortedByZ.add(lbc);
} else {
if (parent->isPendingRemoval()) {
ALOGE("addClientLayer called with a removed parent");
return NAME_NOT_FOUND;
}
parent->addChild(lbc);
}
mGraphicBufferProducerList.add(IInterface::asBinder(gbc));
mLayersAdded = true;
mNumLayers++;
}
// attach this layer to the client
client->attachLayer(handle, lbc);
return NO_ERROR;
}
將新創(chuàng)建的Layer添加到當前的layer列表中蛋哭,按照Z-order。如果有parent的涮母,添加到parent中谆趾。mGraphicBufferProducerList保存了當前的所有Layer內(nèi)容的生產(chǎn)者。最后叛本,將Layer關(guān)聯(lián)的Client上沪蓬。
Layer創(chuàng)建完成后,調(diào)用setTransactionFlags函數(shù)来候,告訴SurfaceFlinger跷叉,新增加了Layer,有新的顯示,有很多顯示數(shù)據(jù)需要去更新云挟。SurfaceFlinger根據(jù)flag梆砸,決定是否需要換醒服務(wù)。
uint32_t SurfaceFlinger::setTransactionFlags(uint32_t flags) {
uint32_t old = android_atomic_or(flags, &mTransactionFlags);
if ((old & flags)==0) { // wake the server up
signalTransaction();
}
return old;
}
Layer創(chuàng)建完成园欣,回到我們的應(yīng)用~
處理狀態(tài)的傳送
應(yīng)用的代碼如下:
SurfaceComposerClient::Transaction{}
.setLayer(surfaceControl, 0x7FFFFFFF)
.show(surfaceControl)
.apply();
C++的新特性帖世,是不是有點類似Java了。
從Android P開始沸枯,google又重構(gòu)了這一塊的代碼日矫。之前的代碼中,是SurfaceComposerClient提供全局的狀態(tài)處理绑榴;從Android P開始哪轿,transactions 被區(qū)分為不同的對象,直接處理對象彭沼。這是Transaction一個類圖缔逛。
可見,將處理類型分為了兩類:
- ComposerState 合成處理狀態(tài)
struct ComposerState {
sp<ISurfaceComposerClient> client;
layer_state_t state;
status_t write(Parcel& output) const;
status_t read(const Parcel& input);
};
ComposerState封裝了layer_state_t姓惑,Layer的狀態(tài)褐奴,再實現(xiàn)Binder通信時的write,read于毙。
- DisplayState 顯示屏狀態(tài)
struct DisplayState {
enum {
eOrientationDefault = 0,
eOrientation90 = 1,
eOrientation180 = 2,
eOrientation270 = 3,
eOrientationUnchanged = 4,
eOrientationSwapMask = 0x01
};
enum {
eSurfaceChanged = 0x01,
eLayerStackChanged = 0x02,
eDisplayProjectionChanged = 0x04,
eDisplaySizeChanged = 0x08
};
DisplayState();
void merge(const DisplayState& other);
uint32_t what;
sp<IBinder> token;
sp<IGraphicBufferProducer> surface;
uint32_t layerStack;
uint32_t orientation;
Rect viewport;
Rect frame;
uint32_t width, height;
status_t write(Parcel& output) const;
status_t read(const Parcel& input);
};
Display的狀態(tài)目前就4個敦冬,也就是
enum {
eSurfaceChanged = 0x01, // Surface改變了
eLayerStackChanged = 0x02, // layerStack改變了
eDisplayProjectionChanged = 0x04, // Display的Projection改變了
eDisplaySizeChanged = 0x08 // Size改變了
};
這里的what,就是用以標記mark到底是哪個屬性改變了唯沮,有多個屬性改變的時候脖旱,加上對應(yīng)的mark標記位即可。
ComposerState中的layer_state_t和這里的DisplayState類似介蛉。也是采用what來標記的萌庆。Layer的狀態(tài)處理,包括以下屬性币旧。
enum {
ePositionChanged = 0x00000001,
eLayerChanged = 0x00000002,
eSizeChanged = 0x00000004,
eAlphaChanged = 0x00000008,
eMatrixChanged = 0x00000010,
eTransparentRegionChanged = 0x00000020,
eFlagsChanged = 0x00000040,
eLayerStackChanged = 0x00000080,
eCropChanged = 0x00000100,
eDeferTransaction = 0x00000200,
eFinalCropChanged = 0x00000400,
eOverrideScalingModeChanged = 0x00000800,
eGeometryAppliesWithResize = 0x00001000,
eReparentChildren = 0x00002000,
eDetachChildren = 0x00004000,
eRelativeLayerChanged = 0x00008000,
eReparent = 0x00010000,
eColorChanged = 0x00020000
};
好了践险,讓我們通過本實例中的示例,來看看狀態(tài)處理是怎么傳遞吹菱,生效的巍虫。
setLayer,實際上是設(shè)置Layer的z-order鳍刷,
SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setLayer(
const sp<SurfaceControl>& sc, int32_t z) {
layer_state_t* s = getLayerStateLocked(sc);
if (!s) {
mStatus = BAD_INDEX;
return *this;
}
s->what |= layer_state_t::eLayerChanged;
s->z = z;
return *this;
}
getLayerStateLocked占遥,就是根據(jù)SurfaceCotrol對象去找,對應(yīng)的layer_state_t输瓜。
layer_state_t* SurfaceComposerClient::Transaction::getLayerStateLocked(const sp<SurfaceControl>& sc) {
ComposerState s;
s.client = sc->getClient()->mClient;
s.state.surface = sc->getHandle();
ssize_t index = mComposerStates.indexOf(s);
if (index < 0) {
// we don't have it, add an initialized layer_state to our list
index = mComposerStates.add(s);
}
ComposerState* const out = mComposerStates.editArray();
return &(out[index].state);
}
我們看瓦胎,setLayer時芬萍,增加mask標識what是layer_state_t::eLayerChanged,而對應(yīng)的值保存到layer_state_t z中凛捏。注意担忧,這里的設(shè)置并沒有立即生效。
同樣坯癣,show時瓶盛,也是將對應(yīng)的mask表示加到what中,而是否顯示的標識存放在layer_state_t的flag中示罗。
SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::show(
const sp<SurfaceControl>& sc) {
return setFlags(sc, 0, layer_state_t::eLayerHidden);
}
SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFlags(
const sp<SurfaceControl>& sc, uint32_t flags,
uint32_t mask) {
layer_state_t* s = getLayerStateLocked(sc);
if (!s) {
mStatus = BAD_INDEX;
return *this;
}
if ((mask & layer_state_t::eLayerOpaque) ||
(mask & layer_state_t::eLayerHidden) ||
(mask & layer_state_t::eLayerSecure)) {
s->what |= layer_state_t::eFlagsChanged;
}
s->flags &= ~mask;
s->flags |= (flags & mask);
s->mask |= mask;
return *this;
}
我們設(shè)置的處理狀態(tài)惩猫,在apply時,才生效蚜点。
status_t SurfaceComposerClient::Transaction::apply(bool synchronous) {
if (mStatus != NO_ERROR) {
return mStatus;
}
sp<ISurfaceComposer> sf(ComposerService::getComposerService());
Vector<ComposerState> composerStates;
Vector<DisplayState> displayStates;
uint32_t flags = 0;
mForceSynchronous |= synchronous;
composerStates = mComposerStates;
mComposerStates.clear();
displayStates = mDisplayStates;
mDisplayStates.clear();
if (mForceSynchronous) {
flags |= ISurfaceComposer::eSynchronous;
}
if (mAnimation) {
flags |= ISurfaceComposer::eAnimation;
}
mForceSynchronous = false;
mAnimation = false;
sf->setTransactionState(composerStates, displayStates, flags);
mStatus = NO_ERROR;
return NO_ERROR;
}
apply時轧房,最重要的就是調(diào)用setTransactionState,
void SurfaceFlinger::setTransactionState(
const Vector<ComposerState>& state,
const Vector<DisplayState>& displays,
uint32_t flags)
{
ATRACE_CALL();
Mutex::Autolock _l(mStateLock);
uint32_t transactionFlags = 0;
if (flags & eAnimation) {
... ...
// Animation flag的處理绍绘,在Androd P上很少用到,重要是用做模擬back-pressure
}
// 處理Display State
size_t count = displays.size();
for (size_t i=0 ; i<count ; i++) {
const DisplayState& s(displays[i]);
transactionFlags |= setDisplayStateLocked(s);
}
// 處理layer State
count = state.size();
for (size_t i=0 ; i<count ; i++) {
const ComposerState& s(state[i]);
... ...
if (s.client != NULL) {
sp<IBinder> binder = IInterface::asBinder(s.client);
if (binder != NULL) {
if (binder->queryLocalInterface(ISurfaceComposerClient::descriptor) != NULL) {
sp<Client> client( static_cast<Client *>(s.client.get()) );
transactionFlags |= setClientStateLocked(client, s.state);
}
}
}
}
// 處理假動畫和同步模式
if (transactionFlags == 0 &&
((flags & eSynchronous) || (flags & eAnimation))) {
transactionFlags = eTransactionNeeded;
}
if (transactionFlags) {
... ...
}
}
SurfaceFlinger中奶镶,處理狀態(tài)是怎么工作的呢?
SurfaceF中陪拘,有兩個狀態(tài): mCurrentState 和 mDrawingState厂镇。
- mCurrentState主要是用作接受Client的處理變更請求;需要狀態(tài)鎖mStateLock的保護
- mDrawingState主要用作左刽,控制合成捺信;只能在SurfaceFlinger的主線程中使用,不需要鎖的保護欠痴。
其實這很好理解迄靠,每個狀態(tài)中都有顯示數(shù)據(jù)及其處理的描述。mCurrentState在做顯示數(shù)據(jù)的準備喇辽,mDrawingState狀態(tài)掌挚,就是將顯示數(shù)據(jù)合成送給Display。兩個處理同時進行菩咨,兩個都處理完后疫诽,再將mCurrentState處理狀態(tài),給到mDrawingState旦委。主線程根據(jù)mDrawingState中描述的顯示數(shù)據(jù)和處理,把數(shù)據(jù)進行合成雏亚。
狀態(tài)的處理缨硝,同樣分為Display和Layer。
Client端采用Mask標記的方式罢低,標記處理狀態(tài)的改變查辩。SurfaceFlinger這邊收到后胖笛,根據(jù)mask標記,再將參數(shù)還原出來宜岛。保存到mCurrentState中长踊。Display狀態(tài)的處理如下:
uint32_t SurfaceFlinger::setDisplayStateLocked(const DisplayState& s)
{
ssize_t dpyIdx = mCurrentState.displays.indexOfKey(s.token);
if (dpyIdx < 0)
return 0;
uint32_t flags = 0;
DisplayDeviceState& disp(mCurrentState.displays.editValueAt(dpyIdx));
if (disp.isValid()) {
const uint32_t what = s.what;
... ...
if (what & DisplayState::eDisplaySizeChanged) {
if (disp.width != s.width) {
disp.width = s.width;
flags |= eDisplayTransactionNeeded;
}
if (disp.height != s.height) {
disp.height = s.height;
flags |= eDisplayTransactionNeeded;
}
}
}
return flags;
}
Layer狀態(tài)的處理也是類似的,我們來看一下z-order的處理萍倡。
uint32_t SurfaceFlinger::setClientStateLocked(
const sp<Client>& client,
const layer_state_t& s)
{
... ...
if (what & layer_state_t::eLayerChanged) {
// NOTE: index needs to be calculated before we update the state
const auto& p = layer->getParent();
if (p == nullptr) {
ssize_t idx = mCurrentState.layersSortedByZ.indexOf(layer);
if (layer->setLayer(s.z) && idx >= 0) {
mCurrentState.layersSortedByZ.removeAt(idx);
mCurrentState.layersSortedByZ.add(layer);
// we need traversal (state changed)
// AND transaction (list changed)
flags |= eTransactionNeeded|eTraversalNeeded;
}
} else {
if (p->setChildLayer(layer, s.z)) {
flags |= eTransactionNeeded|eTraversalNeeded;
}
}
}
... ...
}
SurfaceFlinger有兩個狀態(tài)身弊,Layer也是有兩個狀態(tài)的。
bool Layer::setLayer(int32_t z) {
if (mCurrentState.z == z) return false;
mCurrentState.sequence++;
mCurrentState.z = z;
mCurrentState.modified = true;
// Discard all relative layering.
if (mCurrentState.zOrderRelativeOf != nullptr) {
sp<Layer> strongRelative = mCurrentState.zOrderRelativeOf.promote();
if (strongRelative != nullptr) {
strongRelative->removeZOrderRelative(this);
}
mCurrentState.zOrderRelativeOf = nullptr;
}
setTransactionFlags(eTransactionNeeded);
return true;
}
到此列敲,我們的WindowSurfaceWrapper基本算構(gòu)建完成阱佛。
小結(jié)
本章從Native應(yīng)用的角度出發(fā),講解了應(yīng)用怎么和SurfaceFlinger建立聯(lián)系戴而,同時介紹了SurfaceFlinger的啟動凑术。我們做應(yīng)用開發(fā),坑需要根據(jù)實際的屏幕參數(shù)來做所意,所以介紹了怎么獲取顯示屏參數(shù)信息淮逊;SurfaceFlinger中顯示的數(shù)據(jù)都是通過Layer進行封裝,介紹了創(chuàng)建Layer的過程扶踊。最后泄鹏,介紹了,顯示的數(shù)據(jù)參數(shù)姻檀,也就說處理的狀態(tài)命满,怎么從Client端傳到SurfaceFlinger的。