[TOC]
上層Client和SurfaceFlinger的交互
為了很好的切入主題,我們這里基于Native的Framework進行應用的開發呢,不是指的NDK應用。我們直接用系統接口,進行開發。Native應用直接拋棄掉Android的Java上層,AMS,WMS,View等,直接在Native開發,這樣便于我們理解顯示系統。
Native應用建立
在顯示子系統中,Surface是一個很重要的類,通過Surface我們就能獲取到Buffer,我們就能夠和Android Native窗口系統建立連接。我們就基于Surface來寫一個Native的應用。
首先,我們先定義一個封裝類WindowSurfaceWrapper,WindowSurfaceWrapper和Surface進行交互。
class WindowSurfaceWrapper : public RefBase {
public:
// Creates the window.
WindowSurfaceWrapper(const String8& name);
virtual ~WindowSurfaceWrapper() {}
virtual void onFirstRef();
// Retrieves a handle to the window.
sp<ANativeWindow> getSurface() const;
int width() {
return mWidth;
}
int height() {
return mHeight;
}
private:
WindowSurfaceWrapper(const WindowSurfaceWrapper&);
WindowSurfaceWrapper& operator=(const WindowSurfaceWrapper&);
sp<SurfaceControl> mSurfaceControl;
int mWidth;
int mHeight;
String8 mName;
};
WindowSurfaceWrapper對應的實現如下:
WindowSurfaceWrapper::WindowSurfaceWrapper(const String8& name) {
mName = name;
}
void WindowSurfaceWrapper::onFirstRef() {
status_t err;
sp<SurfaceComposerClient> surfaceComposerClient = new SurfaceComposerClient;
err = surfaceComposerClient->initCheck();
if (err != NO_ERROR) {
fprintf(stderr, "SurfaceComposerClient::initCheck error: %#x\n", err);
return;
}
// Get main display parameters.
sp<IBinder> mainDisplay = SurfaceComposerClient::getBuiltInDisplay(
ISurfaceComposer::eDisplayIdMain);
DisplayInfo mainDisplayInfo;
err = SurfaceComposerClient::getDisplayInfo(mainDisplay, &mainDisplayInfo);
if (err != NO_ERROR) {
fprintf(stderr, "ERROR: unable to get display characteristics\n");
return;
}
uint32_t width, height;
if (mainDisplayInfo.orientation != DISPLAY_ORIENTATION_0 &&
mainDisplayInfo.orientation != DISPLAY_ORIENTATION_180) {
// rotated
width = mainDisplayInfo.h;
height = mainDisplayInfo.w;
} else {
width = mainDisplayInfo.w;
height = mainDisplayInfo.h;
}
sp<SurfaceControl> surfaceControl = surfaceComposerClient->createSurface(
mName, width, height,
PIXEL_FORMAT_RGBX_8888, ISurfaceComposerClient::eOpaque);
if (surfaceControl == NULL || !surfaceControl->isValid()) {
fprintf(stderr, "Failed to create SurfaceControl\n");
return;
}
SurfaceComposerClient::Transaction{}
.setLayer(surfaceControl, 0x7FFFFFFF)
.show(surfaceControl)
.apply();
mSurfaceControl = surfaceControl;
mWidth = width;
mHeight = height;
}
sp<ANativeWindow> WindowSurfaceWrapper::getSurface() const {
sp<ANativeWindow> anw = mSurfaceControl->getSurface();
return anw;
}
getSurface
獲取Native 窗口,這個窗口能夠和Native的窗口系統建立聯系,我們直接往這個窗口里面繪制我們需要的界面就OK了。
int main(int argc, char *argv[]) {
unsigned samples = 0;
printf("usage: %s [samples]\n", argv[0]);
if (argc == 2) {
samples = atoi( argv[1] );
printf("Multisample enabled: GL_SAMPLES = %u\n", samples);
}
sp<ProcessState> proc(ProcessState::self());
ProcessState::self()->startThreadPool();
sp<WindowSurfaceWrapper> windowSurface(new WindowSurfaceWrapper(String8("NativeBinApp")));
drawNativeWindow(windowSurface->getSurface().get(), windowSurface->width(), windowSurface->height());
IPCThreadState::self()->joinThreadPool();
return EXIT_SUCCESS;
}
解釋一下代碼中的關鍵點:
- 創建一個SurfaceComposerClient,這是應用端,是SurfaceFlinger的Client端,它將建立和SurfaceFlinger服務的通信
- getDisplayInfo,獲取手機屏幕的信息
- createSurface,創建SurfaceControl,在SurfaceFlinger創建對應的Layer等~
- setLayer,設置窗口的z-Oder,SurfaceFlinger根據z-Oder決定窗口的可見性及可見大小
- show,讓當前窗口可見
- apply,這時,上面的設置的屬性才真正生效,傳給SurfaceFlinger
至于怎么畫界面,我們接來下再介紹,稍后再給出drawNativeWindow的代碼。我們先來看,目前都干了什么。
應用和SurfaceFlinger的鏈接建立
應用和SurfaceFlinger是兩個不同的進程,他們采用Binder通信,應用是Client端,SurfaceFlinger是服務端。在Android中ProcessState是客戶端和服務端公共的部分,作為Binder通信的基礎,ProcessState是一個singleton類,每個進程只有一個對象,這個對象負責打開Binder驅動,建立線程池,讓其進程里面的所有線程都能通過Binder通信。與之相關的是IPCThreadState,每個線程都有一個IPCThreadState實例登記在Linux線程的上下文附屬數據中,主要負責Binder的讀取,寫入和請求處理框架。IPCThreadState在構造的時候獲取進程的ProcessState并記錄在自己的成員變量mProcess中,通過mProcess可以獲得Binder的句柄。
我們這里將不詳細的介紹Binder。有需求的可以提,我們開一個專題。
SurfaceComposerClient的 定義非常簡單,繼承RefBase~,這樣我們就可以直接用智能指針sp,wp管理SurfaceComposerClient對象,不用擔心SurfaceComposerClient對象的回收問題。
智能指針sp,wp,我們這里也不做詳細的介紹,有需求的可以提,我們開一個專題。
在SurfaceComposerClient的構造函數中,只初始化了一個裝mStatus。
SurfaceComposerClient::SurfaceComposerClient()
: mStatus(NO_INIT)
{
}
第一次引用的時候,才真正的建立連接:
*frameworks/native/libs/gui/SurfaceComposerClient.cpp
void SurfaceComposerClient::onFirstRef() {
sp<ISurfaceComposer> sf(ComposerService::getComposerService());
if (sf != 0 && mStatus == NO_INIT) {
auto rootProducer = mParent.promote();
sp<ISurfaceComposerClient> conn;
conn = (rootProducer != nullptr) ? sf->createScopedConnection(rootProducer) :
sf->createConnection();
if (conn != 0) {
mClient = conn;
mStatus = NO_ERROR;
}
}
}
ComposerService繼承模板類Singleton,ComposerService是一個單例。
ComposerService::ComposerService()
: Singleton<ComposerService>() {
Mutex::Autolock _l(mLock);
connectLocked();
}
ComposerService在構建時,創建鏈接:
void ComposerService::connectLocked() {
const String16 name("SurfaceFlinger");
while (getService(name, &mComposerService) != NO_ERROR) {
usleep(250000);
}
assert(mComposerService != NULL);
// Create the death listener.
class DeathObserver : public IBinder::DeathRecipient {
ComposerService& mComposerService;
virtual void binderDied(const wp<IBinder>& who) {
ALOGW("ComposerService remote (surfaceflinger) died [%p]",
who.unsafe_get());
mComposerService.composerServiceDied();
}
public:
explicit DeathObserver(ComposerService& mgr) : mComposerService(mgr) { }
};
mDeathObserver = new DeathObserver(*const_cast<ComposerService*>(this));
IInterface::asBinder(mComposerService)->linkToDeath(mDeathObserver);
}
建立連接時,采用輪循的方式,getService時,如果SurfaceFlinger服務還沒有啟動,等待250000后再查詢,知道等到SurffaceFlinger進程啟動。DeathObserver是監聽SurfaceFlinger進程是否死掉,做善后處理的。
getComposerService直接返回單實例mComposerService。
/*static*/ sp<ISurfaceComposer> ComposerService::getComposerService() {
ComposerService& instance = ComposerService::getInstance();
Mutex::Autolock _l(instance.mLock);
if (instance.mComposerService == NULL) {
ComposerService::getInstance().connectLocked();
assert(instance.mComposerService != NULL);
ALOGD("ComposerService reconnected");
}
return instance.mComposerService;
}
createScopedConnection函數,將建立和SurfaceFlinger的連接。
void SurfaceComposerClient::onFirstRef() {
sp<ISurfaceComposer> sf(ComposerService::getComposerService());
if (sf != 0 && mStatus == NO_INIT) {
auto rootProducer = mParent.promote();
sp<ISurfaceComposerClient> conn;
conn = (rootProducer != nullptr) ? sf->createScopedConnection(rootProducer) :
sf->createConnection();
if (conn != 0) {
mClient = conn;
mStatus = NO_ERROR;
}
}
}
對于我們這里的使用來說,rootProducer是nullptr,所以直接走的sf->createConnection()。Bn端SurfaceFlinger的實現為:
* frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
sp<ISurfaceComposerClient> SurfaceFlinger::createConnection() {
return initClient(new Client(this));
}
static sp<ISurfaceComposerClient> initClient(const sp<Client>& client) {
status_t err = client->initCheck();
if (err == NO_ERROR) {
return client;
}
return nullptr;
}
Client繼承BnSurfaceComposerClient,是ISurfaceComposerClient的Bn端。
我們來看一下,顯示系統中,Client和SurfaceFlinger的關系:
應用端SurfaceComposerClient通過接口ISurfaceComposerClient和SurfaceFlinger的Client建立聯系。應用端通過的ComposerService通過ISurfaceComposer和SurfaceFlinger建立聯系。
SurfaceFlinger的啟動
SurfaceFlinger是一個系統級的服務,Android系統啟動的過程中就會啟動SurfaceFlinger,在初始化init時。
* frameworks/native/services/surfaceflinger/surfaceflinger.rc
service surfaceflinger /system/bin/surfaceflinger
class core animation
user system
group graphics drmrpc readproc
onrestart restart zygote
writepid /dev/stune/foreground/tasks
socket pdx/system/vr/display/client stream 0666 system graphics u:object_r:pdx_display_client_endpoint_socket:s0
socket pdx/system/vr/display/manager stream 0666 system graphics u:object_r:pdx_display_manager_endpoint_socket:s0
socket pdx/system/vr/display/vsync stream 0666 system graphics u:object_r:pdx_display_vsync_endpoint_socket:s0
既然是獨立的進程,系統級的服務,那就有自己的main函數:
* frameworks/native/services/surfaceflinger/main_surfaceflinger.cpp
int main(int, char**) {
startHidlServices();
signal(SIGPIPE, SIG_IGN);
// When SF is launched in its own process, limit the number of
// binder threads to 4.
ProcessState::self()->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個服務:
- startHidlServices主要是啟動allocator
- DisplayService,主要負責DisplayEvent的處理
- SurfaceFlinger,主要顯示相關的,最重要的服務
- GpuService,GPU相關的服務,為訪問GPU
SurfaceFlinger類定義如下:
* frameworks/native/services/surfaceflinger/SurfaceFlinger.h
class SurfaceFlinger : public BnSurfaceComposer,
public PriorityDumper,
private IBinder::DeathRecipient,
private HWC2::ComposerCallback
SurfaceComposer是ISurfaceComposer的Bn端。實現了HWC2的ComposerCallback回調。死亡回收DeathRecipient,以及Dump信息PriorityDumper。
構造函數如下:
* 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");
... ...
}
在構造函數中,主要是做初始化。從Android O開始,vendor的一些配置,都采用configstore的方式提供,就是這里的ISurfaceFlingerConfigs,這是一個系統服務。對應的接口在 hardware/interfaces/configstore/ 。當然,采用屬性進行設置,但是屬性設置的是debug的參數居多。
SurfaceFlinger真正的初始化,是在init函數中:
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函數中,主要做了一下幾件事:
- 創建兩個EventThread及其DispSyncSource,主要是用以處理和分發如Vsync;App和SurfaceFlinger的如Vsync是分開的,不是同一個。
- 創建了自己的消息隊列mEventQueue,SurfaceFlinger的消息隊列
- 初始化了Client合成模式(GPU)合成時,需要用到的RenderEngine
- 初始化HWComposer,注冊回調接口registerCallback,HAL會回調一些方法。
- 如果是VR模式,創建mVrFlinger
- 創建mEventControlThread,處理Event事件,如Vsync事件和hotplug事件。
- 初始化顯示設備initializeDisplays
SurfaceFlinger第一次引用時,啟動mEventQueue消息隊列
void SurfaceFlinger::onFirstRef()
{
mEventQueue.init(this);
}
SurfaceFlinger這邊后續再繼續,先回到Native應用的創建
獲取Display信息
Android支持多給屏幕,多個屏幕可以顯示一樣的內容,也可以顯示不一樣的內容。我們通常的把他們稱為主顯,外顯和虛顯。主顯就是內置的,默認的手機屏幕;外顯就是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調用,中間的Binder就省掉了,直接看實現:
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];
}
前面初始化的時候,屏幕都是采用熱插拔的形式上報。內置屏幕也是這樣。這個后續再介紹。
獲取屏幕后,通過getDisplayInfo函數,就能獲取屏幕的信息。
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,根據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中getDisplayConfigs的實現之前。我們先來看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}; // 屏幕的旋轉方式
bool secure{false}; // 屏幕是否是安全的
nsecs_t appVsyncOffset{0}; // App的Vsync的偏移
nsecs_t presentationDeadline{0}; // 顯示的最后時間
};
我們結合SurfaceFlinger中getDisplayConfigs的實現,來說說Display的信息。
- 首先,根據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;
}
}
- 在根據type去獲取驅動中配置的信息getConfigs,getHwComposer().getConfigs(type);
ConditionalLock _l(mStateLock,
std::this_thread::get_id() != mMainThreadId);
for (const auto& hwConfig : getHwComposer().getConfigs(type)) {
- 最后,根據驅動給的配置,和一些設置,構建完整的顯示屏信息,下面是關鍵信息,刪掉了一些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)
屏幕的寬高是用分辨率來描述的,也就是像素點的多少。像素是指在由一個數字序列表示的圖像中的一個最小單位,稱為像素。屏幕多寬,就是指,屏幕橫向可以顯示多少個像素點。屏幕多高就是指,屏幕縱向可以顯示多少給像素點。平常所說的720P屏幕,就是1080x720,橫向可以顯示1080個像素點,縱向可以顯示720個像素點。
此圖是,平常什么所說的一些分辨率:
常用的分辨率 每英寸的點數xdpi,ydpi
顯示屏幕的物理大小,用英寸來描述,描述屏幕對角線的長度。比如iPhoneX 5.8英寸,指的是對角線的長度5.8英寸。而dpi,即Dots Per Inch,表示每英寸有多少給點。百度百科的解釋為,dpi是一個量度單位,用于點陣數碼影像,指每一英寸長度中,取樣、可顯示或輸出點的數目。
PPI(pixels per inch)和DPI是措辭的差別,很多時候,都是混用的。如iPhoneX是458 ppi;榮耀V9的DPI為488左右。density密度
這里的desity是一個縮放因子,是 DPI / (160像素/英寸) 后得到的值,是一個比例值。
這可以看DisplayMetrics中關于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;
以設備無關像素DIP(device independent pixels)在160dpi屏幕上顯示為基礎。160dip在160dpi的屏幕上,density就是1,在120dpi的屏幕上,density就為0.75。
屏幕刷新率FPS
FPS(Frame per second),幀每秒。表示屏幕一描述,可以顯示多少幀圖像數據。目前多少的手機顯示屏還是60FPS,顯示一幀16.67ms左右。orientation屏幕旋轉方向
手機默認豎屏,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(數字版權保護)時,確保顯示的設備是安全的,以防止DRM的內容被在顯示的過程中被截取。只有安全的設備才能顯示DRM的內容。
Android默認,所有的非虛擬顯示都是安全的。
// All non-virtual displays are currently considered secure.
info.secure = true;
- appVsyncOffset和presentationDeadline
這兩個都和 Vsync有關,后續會再介紹。appVsyncOffset是一個偏移量,在系統(或硬件Vsync)的基礎上做一些偏移。presentationDeadline表示,一幀數據,多就內,必現要顯示出來。
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服務中,Display的描述,用的DisplayDevice。每添加一個顯示屏,都會創建一個DisplayDevice。
int DisplayDevice::getActiveConfig() const {
return mActiveConfig;
}
activeconfig,是一個索引值,對應驅動中,對應的config的索引。一般來說,active的config,都是默認的0。當然SurfaceFlinger或上層是可以去設置的。
void DisplayDevice::setActiveConfig(int mode) {
mActiveConfig = mode;
}
回到應用~
Native創建圖層Layer
拿到顯示信息后,根據轉屏,這邊的尺寸需要做一下交換。因為不關屏幕怎么旋轉,我們需要顯示的內容大小是沒有變的。
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;
}
createSurface函數如下:
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;
}
先解釋一下,其中的參數:
name
name就是圖層的名字,沒有實際意義,主要是便于debug,有有名字,就可以知道,我們創建的圖層是哪個了。w,h
這個是圖層的寬高,我們用只是從DisplayInfo中讀出來的,跟屏幕的大小一樣。format
圖層的格式,應用中,我們用的格式是PIXEL_FORMAT_RGBX_8888。
我們通過RGB,紅,綠,藍,三原色可以調配所有的顏色。在數字世界里面,也是用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 | 應用保護 | 應用將請求一個安全的硬件通道傳輸到外顯 |
eProtectedByDRM | DRM保護 | 應用請求一個安全的通道傳輸DRM |
eCursorWindow | Cursor Layer | 其實這Layer就是鼠標一類的圖標 |
eFXSurfaceNormal | 普通的Layer | 系統中大多數layer都是此類 |
eFXSurfaceColor | 顏色layer | 在之前的版本中,這個被稱為Dim Layer |
- windowType
窗口類型,可以參照WindowManager.java中的定義,如FIRST_SYSTEM_WINDOW,TYPE_STATUS_BAR等。默認值為0。
- ownerUid
可以指定這個是哪個UID的Layer。
繼續看createSurfface,Service端的實現如下:
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類中,創建Layer時,先找到parent Layer,對于我們的應用來說,是沒有parent Layer的。然后再postMessageSync到SurfaceFlinger中,去創建,調用的SurfaceFlinger的createLayer方法。
SurfaceFlinger中,都是采用post Message的形式調到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兩個接口實現。怎么創建的這里就不介紹了,后續再介紹。
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;
}
將新創建的Layer添加到當前的layer列表中,按照Z-order。如果有parent的,添加到parent中。mGraphicBufferProducerList保存了當前的所有Layer內容的生產者。最后,將Layer關聯的Client上。
Layer創建完成后,調用setTransactionFlags函數,告訴SurfaceFlinger,新增加了Layer,有新的顯示,有很多顯示數據需要去更新。SurfaceFlinger根據flag,決定是否需要換醒服務。
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創建完成,回到我們的應用~
處理狀態的傳送
應用的代碼如下:
SurfaceComposerClient::Transaction{}
.setLayer(surfaceControl, 0x7FFFFFFF)
.show(surfaceControl)
.apply();
C++的新特性,是不是有點類似Java了。
從Android P開始,google又重構了這一塊的代碼。之前的代碼中,是SurfaceComposerClient提供全局的狀態處理;從Android P開始,transactions 被區分為不同的對象,直接處理對象。這是Transaction一個類圖。
可見,將處理類型分為了兩類:
- ComposerState 合成處理狀態
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的狀態,再實現Binder通信時的write,read。
- DisplayState 顯示屏狀態
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的狀態目前就4個,也就是
enum {
eSurfaceChanged = 0x01, // Surface改變了
eLayerStackChanged = 0x02, // layerStack改變了
eDisplayProjectionChanged = 0x04, // Display的Projection改變了
eDisplaySizeChanged = 0x08 // Size改變了
};
這里的what,就是用以標記mark到底是哪個屬性改變了,有多個屬性改變的時候,加上對應的mark標記位即可。
ComposerState中的layer_state_t和這里的DisplayState類似。也是采用what來標記的。Layer的狀態處理,包括以下屬性。
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
};
好了,讓我們通過本實例中的示例,來看看狀態處理是怎么傳遞,生效的。
setLayer,實際上是設置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,就是根據SurfaceCotrol對象去找,對應的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,而對應的值保存到layer_state_t z中。注意,這里的設置并沒有立即生效。
同樣,show時,也是將對應的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;
}
我們設置的處理狀態,在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時,最重要的就是調用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中,處理狀態是怎么工作的呢?
SurfaceF中,有兩個狀態: mCurrentState 和 mDrawingState。
- mCurrentState主要是用作接受Client的處理變更請求;需要狀態鎖mStateLock的保護
- mDrawingState主要用作,控制合成;只能在SurfaceFlinger的主線程中使用,不需要鎖的保護。
其實這很好理解,每個狀態中都有顯示數據及其處理的描述。mCurrentState在做顯示數據的準備,mDrawingState狀態,就是將顯示數據合成送給Display。兩個處理同時進行,兩個都處理完后,再將mCurrentState處理狀態,給到mDrawingState。主線程根據mDrawingState中描述的顯示數據和處理,把數據進行合成。
狀態的處理,同樣分為Display和Layer。
Client端采用Mask標記的方式,標記處理狀態的改變。SurfaceFlinger這邊收到后,根據mask標記,再將參數還原出來。保存到mCurrentState中。Display狀態的處理如下:
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狀態的處理也是類似的,我們來看一下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有兩個狀態,Layer也是有兩個狀態的。
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基本算構建完成。
小結
本章從Native應用的角度出發,講解了應用怎么和SurfaceFlinger建立聯系,同時介紹了SurfaceFlinger的啟動。我們做應用開發,坑需要根據實際的屏幕參數來做,所以介紹了怎么獲取顯示屏參數信息;SurfaceFlinger中顯示的數據都是通過Layer進行封裝,介紹了創建Layer的過程。最后,介紹了,顯示的數據參數,也就說處理的狀態,怎么從Client端傳到SurfaceFlinger的。