一、Android系统启动
Android设备从按下开机键到桌面显示画面,大致过程如下图流程:
开机显示桌面、从桌面点击 App 图标到 Activity显示在屏幕上的过程又是怎样的呢?下面介绍Android系统中的“画家” - SurfaceFlinger.
SurfaceFlinger 启动过程:
二、SurfaceFlinger代码剖析[Android 8.0]
代码路径:/frameworks/native/services/surfaceflinger/
SurfaceFlinger二进制分成surfaceflinger可执行文件(main入口)和libsurfaceflinger.so库文件(功能实现),由main_surfaceflinger.cpp文件编译而成,Android.mk代码模块编译配置如下:
1.【执行文件-surfaceflinger】
###############################################################
# build surfaceflinger's executable
include $(CLEAR_VARS) LOCAL_CLANG := true LOCAL_LDFLAGS_32 := -Wl,--version-script,art/sigchainlib/version-script32.txt -Wl,--export-dynamic
LOCAL_LDFLAGS_64 := -Wl,--version-script,art/sigchainlib/version-script64.txt -Wl,--export-dynamic
LOCAL_CFLAGS := -DLOG_TAG=\"SurfaceFlinger\" LOCAL_INIT_RC := surfaceflinger.rc ifeq ($(TARGET_USES_HWC2),true)
LOCAL_CFLAGS += -DUSE_HWC2
endif LOCAL_SRC_FILES := \
main_surfaceflinger.cpp LOCAL_SHARED_LIBRARIES := \
android.frameworks.displayservice@1.0 \
android.hardware.configstore@1.0 \
android.hardware.configstore-utils \
android.hardware.graphics.allocator@2.0 \
libsurfaceflinger \
libcutils \
libdisplayservicehidl \
liblog \
libbinder \
libhidlbase \
libhidltransport \
libutils \
libui \
libgui \
libdl LOCAL_WHOLE_STATIC_LIBRARIES := libsigchain
LOCAL_STATIC_LIBRARIES := libtrace_proto LOCAL_MODULE := surfaceflinger ifdef TARGET_32_BIT_SURFACEFLINGER
LOCAL_32_BIT_ONLY := true
endif LOCAL_CFLAGS += -Wall -Werror -Wunused -Wunreachable-code include $(BUILD_EXECUTABLE)
SurfaceFlinger可执行二进制文件surfaceflinger由main_surfaceflinger.cpp文件独立编译而成,主要负责搭建进程启动环境:
int main(int, char**) { // 从8.0开始,Android提供了hidl机制,将原先直接由JNI->Native->HAL的接口调用形式,统一规范成hidl service/client交互形式。
// 该方式从一方面规范和统一了Android Framework和HAL的调用机制,但实际上,从项目维度,这种调用方式对性能上开销,将比直接调用的方式要花费更多的时间。
startHidlServices(); signal(SIGPIPE, SIG_IGN);
// When SF is launched in its own process, limit the number of
// binder threads to 4.
ProcessState::self()->setThreadPoolMaxThreadCount(); // start the thread pool
sp<ProcessState> ps(ProcessState::self());
ps->startThreadPool(); // 初始化SurfaceFlinger对象,由强指针指向。SurfaceFlinger继承RefBase类,所以此处一旦new出对象赋给sp指针后,将立刻出发SurfaceFlinger类的onFirstRef方法的调用。
// instantiate surfaceflinger
sp<SurfaceFlinger> flinger = new SurfaceFlinger(); setpriority(PRIO_PROCESS, , PRIORITY_URGENT_DISPLAY); set_sched_policy(, 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(, SP_SYSTEM); // SurfaceFlinger类正式初始化
// initialize before clients can connect
flinger->init(); // SurfaceFlinger向ServiceManager注册Binder服务,这样在其他进程中,可以通过getService+SERVICE_NAME来获取SurfaceFlinger服务,继而可以和SurfaceFlinger类进行Binder通信。
// publish surface flinger
sp<IServiceManager> sm(defaultServiceManager());
sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false); // publish GpuService
sp<GpuService> gpuservice = new GpuService();
sm->addService(String16(GpuService::SERVICE_NAME), gpuservice, false); struct sched_param param = {};
param.sched_priority = ;
if (sched_setscheduler(, SCHED_FIFO, ¶m) != ) {
ALOGE("Couldn't set SCHED_FIFO");
} // SurfaceFlinger类进入主循环(此处注意SurfaceFlinger类未继承Threads类,不遵循Threads类的接口执行顺序)
// run surface flinger in this thread
flinger->run(); return ;
}
startHidlServices();内容如下
static status_t startHidlServices() {
using android::frameworks::displayservice::V1_0::implementation::DisplayService;
using android::frameworks::displayservice::V1_0::IDisplayService;
using android::hardware::configstore::getBool;
using android::hardware::configstore::getBool;
using android::hardware::configstore::V1_0::ISurfaceFlingerConfigs;
hardware::configureRpcThreadpool( /* maxThreads */,
false /* callerWillJoin */); status_t err; if (getBool<ISurfaceFlingerConfigs,
&ISurfaceFlingerConfigs::startGraphicsAllocatorService>(false)) {
err = startGraphicsAllocatorService();
if (err != OK) {
return err;
}
} sp<IDisplayService> displayservice = new DisplayService(); //里面调用HIDL定义接口 Return<sp<IDisplayEventReceiver >> getEventReceiver() override;
err = displayservice->registerAsService(); if (err != OK) {
ALOGE("Could not register IDisplayService service.");
} return err;
}
HIDL接口介绍可以参考:https://source.android.google.cn/reference/hidl/
2.【动态库-libsurfaceflinger.so】
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS) LOCAL_CLANG := true LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
LOCAL_SRC_FILES := \
Client.cpp \
DisplayDevice.cpp \
DispSync.cpp \
EventControlThread.cpp \
StartBootAnimThread.cpp \
EventThread.cpp \
FrameTracker.cpp \
GpuService.cpp \
Layer.cpp \
LayerDim.cpp \
LayerRejecter.cpp \
LayerVector.cpp \
MessageQueue.cpp \
MonitoredProducer.cpp \
SurfaceFlingerConsumer.cpp \
SurfaceInterceptor.cpp \
Transform.cpp \
DisplayHardware/ComposerHal.cpp \
DisplayHardware/FramebufferSurface.cpp \
DisplayHardware/HWC2.cpp \
DisplayHardware/HWComposerBufferCache.cpp \
DisplayHardware/PowerHAL.cpp \
DisplayHardware/VirtualDisplaySurface.cpp \
Effects/Daltonizer.cpp \
EventLog/EventLogTags.logtags \
EventLog/EventLog.cpp \
RenderEngine/Description.cpp \
RenderEngine/Mesh.cpp \
RenderEngine/Program.cpp \
RenderEngine/ProgramCache.cpp \
RenderEngine/GLExtensions.cpp \
RenderEngine/RenderEngine.cpp \
RenderEngine/Texture.cpp \
RenderEngine/GLES20RenderEngine.cpp \ LOCAL_MODULE := libsurfaceflinger
LOCAL_C_INCLUDES := \
frameworks/native/vulkan/include \
external/vulkan-validation-layers/libs/vkjson \
system/libhwbinder/fast_msgq/include \ LOCAL_CFLAGS := -DLOG_TAG=\"SurfaceFlinger\"
LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES ifeq ($(TARGET_USES_HWC2),true)
LOCAL_CFLAGS += -DUSE_HWC2
LOCAL_SRC_FILES += \
SurfaceFlinger.cpp \
DisplayHardware/HWComposer.cpp
else
LOCAL_SRC_FILES += \
SurfaceFlinger_hwc1.cpp \
DisplayHardware/HWComposer_hwc1.cpp
endif LOCAL_CFLAGS += -fvisibility=hidden -Werror=format LOCAL_STATIC_LIBRARIES := \
libhwcomposer-command-buffer \
libtrace_proto \
libvkjson \
libvr_manager \
libvrflinger LOCAL_SHARED_LIBRARIES := \
android.frameworks.vr.composer@1.0 \
android.hardware.graphics.allocator@2.0 \
android.hardware.graphics.composer@2.1 \
android.hardware.configstore@1.0 \
android.hardware.configstore-utils \
libcutils \
liblog \
libdl \
libfmq \
libhardware \
libhidlbase \
libhidltransport \
libhwbinder \
libutils \
libEGL \
libGLESv1_CM \
libGLESv2 \
libbinder \
libui \
libgui \
libpowermanager \
libvulkan \
libsync \
libprotobuf-cpp-lite \
libbase \
android.hardware.power@1.0 LOCAL_EXPORT_SHARED_LIBRARY_HEADERS := \
android.hardware.graphics.allocator@2.0 \
android.hardware.graphics.composer@2.1 \
libhidlbase \
libhidltransport \
libhwbinder LOCAL_CFLAGS += -Wall -Werror -Wunused -Wunreachable-code include $(BUILD_SHARED_LIBRARY)
new SurfaceFlinger(); 会执行到:onFirstRef()
void SurfaceFlinger::onFirstRef()
{
mEventQueue.init(this);
}
onFirstRef() 中会创建 Handler 并初始化:
//MessageQueue.cpp
void MessageQueue::init(const sp<SurfaceFlinger>& flinger)
{
mFlinger = flinger;
mLooper = new Looper(true);
mHandler = new Handler(*this);
}
然后会执行到 SurfaceFlinger::init(),该方法主要功能是:
- 初始化 EGL
- 创建 HWComposer
- 初始化非虚拟显示屏
- 启动 EventThread 线程
- 启动开机动画
void SurfaceFlinger::init() {
ALOGI( "SurfaceFlinger's main thread ready to run. "
"Initializing graphics H/W..."); Mutex::Autolock _l(mStateLock); // initialize EGL for the default display
mEGLDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
eglInitialize(mEGLDisplay, NULL, NULL); // start the EventThread
sp<VSyncSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSync,
vsyncPhaseOffsetNs, true, "app");
mEventThread = new EventThread(vsyncSrc, *this, false);
sp<VSyncSource> sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync,
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 = {};
param.sched_priority = ;
if (sched_setscheduler(mSFEventThread->getTid(), SCHED_FIFO, ¶m) != ) {
ALOGE("Couldn't set SCHED_FIFO for SFEventThread");
}
if (sched_setscheduler(mEventThread->getTid(), SCHED_FIFO, ¶m) != ) {
ALOGE("Couldn't set SCHED_FIFO for EventThread");
} // Initialize the H/W composer object. There may or may not be an
// actual hardware composer underneath.
mHwc = new HWComposer(this,
*static_cast<HWComposer::EventHandler *>(this)); // get a RenderEngine for the given display / config (can't fail)
mRenderEngine = RenderEngine::create(mEGLDisplay, mHwc->getVisualID()); // retrieve the EGL context that was selected/created
mEGLContext = mRenderEngine->getEGLContext(); LOG_ALWAYS_FATAL_IF(mEGLContext == EGL_NO_CONTEXT,
"couldn't create EGLContext"); // Inform native graphics APIs that the present timestamp is NOT supported:
property_set(kTimestampProperty, ""); // initialize our non-virtual displays
for (size_t i= ; i<DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES ; i++) {
DisplayDevice::DisplayType type((DisplayDevice::DisplayType)i);
// set-up the displays that are already connected
if (mHwc->isConnected(i) || type==DisplayDevice::DISPLAY_PRIMARY) {
// All non-virtual displays are currently considered secure.
bool isSecure = true;
createBuiltinDisplayLocked(type);
wp<IBinder> token = mBuiltinDisplays[i]; sp<IGraphicBufferProducer> producer;
sp<IGraphicBufferConsumer> consumer;
BufferQueue::createBufferQueue(&producer, &consumer); sp<FramebufferSurface> fbs = new FramebufferSurface(*mHwc, i,
consumer);
int32_t hwcId = allocateHwcDisplayId(type);
sp<DisplayDevice> hw = new DisplayDevice(this,
type, hwcId, mHwc->getFormat(hwcId), isSecure, token,
fbs, producer,
mRenderEngine->getEGLConfig(), false);
if (i > DisplayDevice::DISPLAY_PRIMARY) {
// FIXME: currently we don't get blank/unblank requests
// for displays other than the main display, so we always
// assume a connected display is unblanked.
ALOGD("marking display %zu as acquired/unblanked", i);
hw->setPowerMode(HWC_POWER_MODE_NORMAL);
}
mDisplays.add(token, hw);
}
} // make the GLContext current so that we can create textures when creating Layers
// (which may happens before we render something)
getDefaultDisplayDeviceLocked()->makeCurrent(mEGLDisplay, mEGLContext); mEventControlThread = new EventControlThread(this);
mEventControlThread->run("EventControl", PRIORITY_URGENT_DISPLAY); // set a fake vsync period if there is no HWComposer
if (mHwc->initCheck() != NO_ERROR) {
mPrimaryDispSync.setPeriod();
} // initialize our drawing state
mDrawingState = mCurrentState; // set initial conditions (e.g. unblank default device)
initializeDisplays(); mRenderEngine->primeCache(); mStartBootAnimThread = new StartBootAnimThread();
if (mStartBootAnimThread->Start() != NO_ERROR) {
ALOGE("Run StartBootAnimThread failed!");
} ALOGV("Done initializing");
}
创建 HWComposer:
HWComposer::HWComposer(
const sp<SurfaceFlinger>& flinger,
EventHandler& handler)
: mFlinger(flinger),
mFbDev(), mHwc(), mNumDisplays(),
mCBContext(new cb_context),
mEventHandler(handler),
mDebugForceFakeVSync(false)
{
for (size_t i = ; i<MAX_HWC_DISPLAYS ; i++) {
mLists[i] = ;
} for (size_t i= ; i<HWC_NUM_PHYSICAL_DISPLAY_TYPES ; i++) {
mLastHwVSync[i] = ;
mVSyncCounts[i] = ;
} char value[PROPERTY_VALUE_MAX];
property_get("debug.sf.no_hw_vsync", value, "");
mDebugForceFakeVSync = atoi(value); bool needVSyncThread = true; // Note: some devices may insist that the FB HAL be opened before HWC.
int fberr = loadFbHalModule(); //加载 framebuffer 的 HAL 层模块
loadHwcModule(); //加载 HWComposer 模块 if (mFbDev && mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
// close FB HAL if we don't needed it.
// FIXME: this is temporary until we're not forced to open FB HAL
// before HWC.
framebuffer_close(mFbDev);
mFbDev = NULL;
} // If we have no HWC, or a pre-1.1 HWC, an FB dev is mandatory.
if ((!mHwc || !hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1))
&& !mFbDev) {
ALOGE("ERROR: failed to open framebuffer (%s), aborting",
strerror(-fberr));
abort();
} // these display IDs are always reserved
for (size_t i= ; i<NUM_BUILTIN_DISPLAYS ; i++) {
mAllocatedDisplayIDs.markBit(i);
} if (mHwc) {
ALOGI("Using %s version %u.%u", HWC_HARDWARE_COMPOSER,
(hwcApiVersion(mHwc) >> ) & 0xff,
(hwcApiVersion(mHwc) >> ) & 0xff);
if (mHwc->registerProcs) {
mCBContext->hwc = this;
mCBContext->procs.invalidate = &hook_invalidate;
// VSYNC 信号的回调方法
mCBContext->procs.vsync = &hook_vsync;
if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1))
mCBContext->procs.hotplug = &hook_hotplug;
else
mCBContext->procs.hotplug = NULL;
memset(mCBContext->procs.zero, , sizeof(mCBContext->procs.zero));
// 注册回调函数
mHwc->registerProcs(mHwc, &mCBContext->procs);
} // don't need a vsync thread if we have a hardware composer
needVSyncThread = false;
// always turn vsync off when we start
eventControl(HWC_DISPLAY_PRIMARY, HWC_EVENT_VSYNC, ); // the number of displays we actually have depends on the
// hw composer version
if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_3)) {
// 1.3 adds support for virtual displays
mNumDisplays = MAX_HWC_DISPLAYS;
} else if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
// 1.1 adds support for multiple displays
mNumDisplays = NUM_BUILTIN_DISPLAYS;
} else {
mNumDisplays = ;
}
} if (mFbDev) {
ALOG_ASSERT(!(mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)),
"should only have fbdev if no hwc or hwc is 1.0"); DisplayData& disp(mDisplayData[HWC_DISPLAY_PRIMARY]);
disp.connected = true;
disp.format = mFbDev->format;
DisplayConfig config = DisplayConfig();
config.width = mFbDev->width;
config.height = mFbDev->height;
config.xdpi = mFbDev->xdpi;
config.ydpi = mFbDev->ydpi;
config.refresh = nsecs_t(1e9 / mFbDev->fps);
disp.configs.push_back(config);
disp.currentConfig = ;
} else if (mHwc) {
// here we're guaranteed to have at least HWC 1.1
for (size_t i = ; i<NUM_BUILTIN_DISPLAYS ; i++) {
queryDisplayProperties(i);
}
} if (needVSyncThread) {
// we don't have VSYNC support, we need to fake it : 不支持硬件的 VSYNC,则会创建线程来模拟定时 VSYNC 信号
mVSyncThread = new VSyncThread(*this);
}
}
HWComposer 代表着硬件显示设备,注册了 VSYNC 信号的回调。VSYNC 信号本身是由显示驱动产生的,在不支持硬件的 VSYNC,则会创建“VSyncThread”线程来模拟定时 VSYNC 信号。当硬件产生VSYNC信号时,则会发送消息,handler 收到消息进行处理。当 SurfaceFlinger 进程收到 VSync 信号后经层层调用,最终调用到该对象的 handleMessageRefresh() 方法。
- HSYNC 信号用于告诉电子枪该扫描下一行了, 即要转到下一行起始处了;
- VSYNC 信号告诉电子枪该显示下一帧了, 即该转回左上角起始处了;
// SurfaceFlinger.cpp
void SurfaceFlinger::handleMessageRefresh() {
ATRACE_CALL();
preComposition();//处理显示设备与 layers 的改变,更新光标
rebuildLayerStacks();//重建所有可见 Layer 列表,根据Z轴排序
setUpHWComposer();//更新 HWComposer 图层
doDebugFlashRegions();
doComposition();//生成 OpenGL 纹理图像
postComposition();//将图像传递到物理屏幕
}
相关问题:
① 屏幕刷新速率比系统帧速率快:
此时,在前缓冲区内容全部映射到屏幕上之后,后缓冲区尚未准备好下一帧,屏幕将无法读取下一帧,所以只能继续显示当前一帧的图形,造成一帧显示多次,也就是卡顿。
② 系统帧速率比屏幕刷新率快
此时,屏幕未完全把前缓冲区的一帧映射到屏幕,而系统已经在后缓冲区准备好了下一帧,并要求读取下一帧到屏幕,将会导致屏幕上半部分是上一帧的图形,而下半部分是下一帧的图形,造成屏幕上显示多帧,也就是屏幕撕裂。
为了解决上述问题,Android显示系统一般会有多级缓冲,即在屏幕刷新的同时在另外一个buffer准备下一帧数据,以此提高性能:
前缓冲区:用来显示内容到屏幕的帧缓冲区
后缓冲区:用于后台合成下一帧图形的帧缓冲区
垂直同步(VSync):当屏幕从缓冲区扫描完一帧到屏幕上之后,开始扫描下一帧之前,发出的一个同步信号,该信号用来切换前缓冲区和后缓冲区。
屏幕刷新率(HZ):代表屏幕在一秒内刷新屏幕的次数,Android手机一般为60HZ(也就是1秒刷新60帧,大约16.67毫秒刷新1帧)
系统帧速率(FPS):代表了系统在一秒内合成的帧数,该值的大小由系统算法和硬件决定。
3. 服务启动配置文件:/frameworks/native/services/surfaceflinger/surfaceflinger.rc 上面发现服务配置文件也在Android.mk中被加载:LOCAL_INIT_RC := 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
4. Surface 创建过程
Surface 创建的过程就是 Activity 显示的过程,在 ActivityThread.handleResumeActivity() 中调用了 Activity.makeVisible()具体实现:
void makeVisible() {
if (!mWindowAdded) {
ViewManager wm = getWindowManager();//此处 getWindowManager 获取的是 WindowManagerImpl 对象
wm.addView(mDecor, getWindow().getAttributes());
mWindowAdded = true;
}
mDecor.setVisibility(View.VISIBLE);
}
WindowManagerImpl.java:
public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
applyDefaultToken(params);
mGlobal.addView(view, params, mDisplay, mParentWindow);
}
WindowManagerGlobal.java:
public void addView(View view, ViewGroup.LayoutParams params, Display display, Window parentWindow) {
...
final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams) params;
//创建 ViewRootImpl
ViewRootImpl root = new ViewRootImpl(view.getContext(), display);
view.setLayoutParams(wparams);
mViews.add(view);
mRoots.add(root);
mParams.add(wparams);
//设置 View
root.setView(view, wparams, panelParentView);
...
}
创建 ViewRootImpl:
public final class ViewRootImpl implements ViewParent,
View.AttachInfo.Callbacks, ThreadedRenderer.DrawCallbacks {
...
final Surface mSurface = new Surface(); //创建 Surface,此时 Surface 创建完什么都没有,详见下面分析
...
public ViewRootImpl(Context context, Display display) {
mContext = context;
//获取 IWindowSession 的代理类
mWindowSession = WindowManagerGlobal.getWindowSession();
mDisplay = display;
mThread = Thread.currentThread(); //主线程
mWindow = new W(this);
mChoreographer = Choreographer.getInstance();
...
}
}
WindowManagerGlobal.java:
public static IWindowSession getWindowSession() {
synchronized (WindowManagerGlobal.class) {
if (sWindowSession == null) {
try {
//获取 IMS 的代理类
InputMethodManager imm = InputMethodManager.getInstance();
//获取 WMS 的代理类
IWindowManager windowManager = getWindowManagerService();
//经过 Binder 调用,最终调用 WMS
sWindowSession = windowManager.openSession(
new IWindowSessionCallback.Stub() {...},
imm.getClient(), imm.getInputContext());
} catch (RemoteException e) {
...
}
}
return sWindowSession
}
}
WindowManagerService.openSession:
public IWindowSession openSession(IWindowSessionCallback callback, IInputMethodClient client, IInputContext inputContext) {
//创建 Session 对象
Session session = new Session(this, callback, client, inputContext);
return session;
}
再次经过 Binder 将数据写回 app 进程,则获取的便是 Session 的代理对象 IWindowSession。
创建完 ViewRootImpl 对象后,接下来调用该对象的 setView() 方法:
ViewRootImpl:
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
synchronized (this) { requestLayout(); //详见下面分析
...
//通过 Binder调用,进入 system 进程的 Session
res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
getHostVisibility(), mDisplay.getDisplayId(),
mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
mAttachInfo.mOutsets, mInputChannel);
...
}
}
final class Session extends IWindowSession.Stub implements IBinder.DeathRecipient { public int addToDisplay(IWindow window, int seq, WindowManager.LayoutParams attrs, int viewVisibility, int displayId, Rect outContentInsets, Rect outStableInsets, Rect outOutsets, InputChannel outInputChannel) {
//调用 WMS.addWindow
return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId,
outContentInsets, outStableInsets, outOutsets, outInputChannel);
}
}
WindowManagerService.java:
public int addWindow(Session session, IWindow client, int seq, WindowManager.LayoutParams attrs, int viewVisibility, int displayId, Rect outContentInsets, Rect outStableInsets, Rect outOutsets, InputChannel outInputChannel) {
...
WindowToken token = mTokenMap.get(attrs.token);
//创建 WindowState
WindowState win = new WindowState(this, session, client, token,
attachedWindow, appOp[], seq, attrs, viewVisibility, displayContent);
...
//调整 WindowManager 的 LayoutParams 参数
mPolicy.adjustWindowParamsLw(win.mAttrs);
res = mPolicy.prepareAddWindowLw(win, attrs);
addWindowToListInOrderLocked(win, true);
// 设置 input
mInputManager.registerInputChannel(win.mInputChannel, win.mInputWindowHandle);
//详见下面分析
win.attach();
mWindowMap.put(client.asBinder(), win); if (win.canReceiveKeys()) {
//当该窗口能接收按键事件,则更新聚焦窗口
focusChanged = updateFocusedWindowLocked(UPDATE_FOCUS_WILL_ASSIGN_LAYERS,
false /*updateInputWindows*/);
}
assignLayersLocked(displayContent.getWindowList());
...
} //WindowState.java
void attach() {
mSession.windowAddedLocked();
}
创建 SurfaceSession 对象,并将当前 Session 添加到 WMS.mSessions 成员变量。
Session.java:
void windowAddedLocked() {
if (mSurfaceSession == null) {
mSurfaceSession = new SurfaceSession();
mService.mSessions.add(this);
if (mLastReportedAnimatorScale != mService.getCurrentAnimatorScale()) {
mService.dispatchNewAnimatorScaleLocked(this);
}
}
mNumWindow++;
}
SurfaceSession 的创建会调用 JNI,在 JNI 调用 nativeCreate()。
android_view_SurfaceSession.cpp:
static jlong nativeCreate(JNIEnv* env, jclass clazz) {
SurfaceComposerClient* client = new SurfaceComposerClient();
client->incStrong((void*)nativeCreate);
return reinterpret_cast<jlong>(client);
}
创建 SurfaceComposerClient 对象, 作为跟 SurfaceFlinger 通信的代理对象。
SurfaceComposerClient::SurfaceComposerClient() {
//getComposerService() 将返回 SF 的 Binder 代理端的 BpSurfaceFlinger 对象
sp<ISurfaceComposer> sm(getComposerService()); //先调用 SF 的 createConnection(),再调用_init
_init(sm, sm->createConnection());
if(mClient != ) {
Mutex::Autolock _l(gLock); //gActiveConnections 是全局变量,把刚才创建的 client 保存到这个 map 中去
gActiveConnections.add(mClient->asBinder(), this);
}
}
SurfaceFlinger.cpp:
sp<ISurfaceFlingerClient>SurfaceFlinger::createConnection() {
Mutex::Autolock _l(mStateLock);
uint32_t token = mTokens.acquire(); //先创建一个Client
sp<Client> client = new Client(token, this); //把这个Client对象保存到mClientsMap中,token是它的标识。
status_t err = mClientsMap.add(token, client); /*
创建一个用于 Binder 通信的 BClient,BClient 派生于 ISurfaceFlingerClient,
它的作用是接受客户端的请求,然后把处理提交给 SF,注意,并不是提交给 Client。
Client 会创建一块共享内存,该内存由 getControlBlockMemory 函数返回。
*/
sp<BClient> bclient = new BClient(this, token,client->getControlBlockMemory());
return bclient;
}
Client::Client(ClientID clientID, constsp<SurfaceFlinger>& flinger):ctrlblk(), cid(clientID), mPid(), mBitmap(), mFlinger(flinger) {
const int pgsize = getpagesize();
//下面这个操作会使 cblksize 为页的大小,目前是4096字节
constint cblksize = ((sizeof(SharedClient)+(pgsize-))&~(pgsize-));
mCblkHeap = new MemoryHeapBase(cblksize, , "SurfaceFlinger Clientcontrol-block"); ctrlblk = static_cast<SharedClient *>(mCblkHeap->getBase());
if(ctrlblk) {
new(ctrlblk) SharedClient;//原来 Surface 的 CB 对象就是在共享内存中创建的这个 SharedClient 对象
}
}
SharedClient:
class SharedClient { public:
SharedClient();
~SharedClient();
status_t validate(size_t token) const;
uint32_t getIdentity(size_t token) const; private:
Mutexlock;
Condition cv; //支持跨进程的同步对象 //NUM_LAYERS_MAX 为 31,SharedBufferStack 是什么?
SharedBufferStack surfaces[ NUM_LAYERS_MAX ]; }; //SharedClient的构造函数,没什么新意,不如Audio的CB对象复杂
SharedClient::SharedClient():lock(Mutex::SHARED), cv(Condition::SHARED) {
}
一个 Client 最多支持 31 个显示层。每一个显示层的生产/消费步调都由会对应的 SharedBufferStack 来控制。而它内部就用了几个成员变量来控制读写位置。
SharedBufferStack.h:
class SharedBufferStack{
......
//Buffer 是按块使用的,每个 Buffer 都有自己的编号,其实就是数组中的索引号。
volatile int32_t head; //FrontBuffer 的编号
volatile int32_t available; //空闲 Buffer 的个数
volatile int32_t queued; //脏 Buffer 的个数,脏 Buffer 表示有新数据的 Buffer
volatile int32_t inUse; //SF 当前正在使用的 Buffer 的编号
volatilestatus_t status; //状态码
......
}
SF 的一个 Client 分配一个跨进程共享的 SharedClient 对象。这个对象有31个 SharedBufferStack 元素,每一个 SharedBufferStack 对应于一个显示层。
一个显示层将创建两个 Buffer,后续的 PageFlipping 就是基于这两个 Buffer 展开的。
接着看 SurfaceComposerClient 中这个_init函数:
void SurfaceComposerClient::_init(
const sp<ISurfaceComposer>& sm, constsp<ISurfaceFlingerClient>& conn) {
mPrebuiltLayerState = ;
mTransactionOpen = ;
mStatus = NO_ERROR;
mControl = ; mClient = conn;// mClient 就是 BClient 的客户端
mControlMemory =mClient->getControlBlock();
mSignalServer = sm;// mSignalServer 就是 BpSurfaceFlinger
//mControl 就是那个创建于共享内存之中的 SharedClient
mControl = static_cast<SharedClient*>(mControlMemory->getBase());
}
创建完 ViewRootImpl 对象后,接下来调用该对象的 setView() 方法。在 setView() 中调用了 requestLayout() 方法我们来看下这个方法:
public void requestLayout() {
checkThread();
mLayoutRequested = true;
scheduleTraversals();
} public void scheduleTraversals() {
if(!mTraversalScheduled) {
mTraversalScheduled = true;
sendEmptyMessage(DO_TRAVERSAL); //发送 DO_TRAVERSAL 消息
}
} public void handleMessage(Message msg) {
switch (msg.what) {
......
case DO_TRAVERSAL:
......
performTraversals();//调用 performTraversals()
......
break;
......
}
} private void performTraversals() {
finalView host = mView;//还记得这mView吗?它就是 DecorView
booleaninitialized = false;
booleancontentInsetsChanged = false;
booleanvisibleInsetsChanged; try {
relayoutResult= // 1. 关键函数relayoutWindow
relayoutWindow(params, viewVisibility,insetsPending);
}
......
draw(fullRedrawNeeded);// 2. 开始绘制
......
} private int relayoutWindow(WindowManager.LayoutParams params, int viewVisibility, boolean insetsPending)throws RemoteException {
//原来是调用 IWindowSession 的 relayout(),暂且记住这个调用
int relayoutResult = sWindowSession.relayout(mWindow, params, (int) (mView.mMeasuredWidth * appScale + 0.5f), (int) (mView.mMeasuredHeight * appScale + 0.5f), viewVisibility, insetsPending, mWinFrame, mPendingContentInsets, mPendingVisibleInsets, mPendingConfiguration, mSurface); //mSurface 做为参数传进去了。
}
......
} private void draw(boolean fullRedrawNeeded) {
Surface surface = mSurface;//mSurface 是 ViewRoot 的成员变量
......
Canvascanvas; try {
int left = dirty.left;
int top = dirty.top;
int right = dirty.right;
int bottom = dirty.bottom; //从 mSurface 中 lock 一块 Canvas
canvas = surface.lockCanvas(dirty);
......
mView.draw(canvas);//调用 DecorView 的 draw 函数,canvas 就是画布
......
//unlock 画布,屏幕上马上就能看到 View 的样子了
surface.unlockCanvasAndPost(canvas);
}
......
}
在 ViewRoot 构造时,会创建一个 Surface,它使用无参构造函数,代码如下所示:
final Surface mSurface = new Surface();
此时创建完的 Surface 是空的,什么都没有。接着继续分析 relayoutWindow(),在 relayoutWindow() 中会调用 IWindowSession 的 relayout(),这是一个跨进程方法会调用到 WMS 中的 Session.relayout(),最后调用到 WindowManagerService.relayoutWindow()。
public int relayoutWindow(Session session,IWindow client,
WindowManager.LayoutParams attrs, int requestedWidth,
int requestedHeight, int viewVisibility, boolean insetsPending,
Rect outFrame, Rect outContentInsets, Rect outVisibleInsets,
Configuration outConfig, SurfaceoutSurface){
..... try {
//win 就是 WinState,这里将创建一个本地的 Surface 对象
Surfacesurface = win.createSurfaceLocked();
if(surface != null) {
//先创建一个本地 surface,然后在 outSurface 的对象上调用 copyFrom
//将本地 Surface 的信息拷贝到 outSurface 中,为什么要这么麻烦呢?
outSurface.copyFrom(surface);
......
}
WindowManagerService.java::WindowState:
Surface createSurfaceLocked() {
......
try {
//mSurfaceSession 就是在 Session 上创建的 SurfaceSession 对象
//这里,以它为参数,构造一个新的 Surface 对象
mSurface = new Surface(mSession.mSurfaceSession, mSession.mPid, mAttrs.getTitle().toString(), , w, h, mAttrs.format, flags);
}
Surface.openTransaction();//打开一个事务处理
......
Surface.closeTransaction();//关闭一个事务处理
......
}
构造 Surface 对象:
public Surface(SurfaceSession s,//传入一个SurfaceSession对象
int pid, String name, int display, int w, int h, int format, int flags) throws OutOfResourcesException {
......
mCanvas = new CompatibleCanvas();
//又一个 native 函数
init(s,pid,name,display,w,h,format,flags);
mName = name;
}
static void Surface_init(JNIEnv*env, jobject clazz, jobject session, jint pid, jstring jname, jint dpy, jint w, jint h, jint format, jintflags) { //从 SurfaceSession 对象中取出之前创建的那个 SurfaceComposerClient 对象
SurfaceComposerClient* client = (SurfaceComposerClient*)env->GetIntField(session, sso.client);
sp<SurfaceControl> surface;//注意它的类型是 SurfaceControl
if (jname == NULL) {
//调用 SurfaceComposerClient 的 createSurface 函数,返回的 surface 是一个 SurfaceControl 类型
surface = client->createSurface(pid, dpy, w, h, format, flags);
} else{
......
} //把这个 surfaceControl 对象设置到 Java 层的 Surface 对象中
setSurfaceControl(env, clazz, surface);
}
在 createSurface 内部会使用 Binder 通信将请求发给 SurfaceFlinger:
sp<ISurface>SurfaceFlinger::createSurface(ClientID clientId, int pid, const String8& name, ISurfaceFlingerClient::surface_data_t* params, DisplayID d, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags) {
sp<LayerBaseClient> layer;//LayerBaseClient 是 Layer 家族的基类
//这里又冒出一个 LayerBaseClient 的内部类,它也叫Surface
sp<LayerBaseClient::Surface> surfaceHandle;
Mutex::Autolock _l(mStateLock); //根据 clientId 找到 createConnection 时加入的那个 Client 对象
sp<Client> client = mClientsMap.valueFor(clientId);
......
//注意这个 id,它的值表示 Client 创建的是第几个显示层
//同时也表示将使用 SharedBufferStatck 数组的第 id 个元素
int32_t id = client->generateId(pid); //一个 Client 不能创建多于 NUM_LAYERS_MAX 个的Layer
if(uint32_t(id) >= NUM_LAYERS_MAX) {
return surfaceHandle;
} //根据 flags 参数来创建不同类型的显示层
switch(flags & eFXSurfaceMask) {
case eFXSurfaceNormal:
if (UNLIKELY(flags & ePushBuffers)) {
//创建 PushBuffer 类型的显示层
layer = createPushBuffersSurfaceLocked(client, d, id, w, h, flags);
} else {
//创建 Normal 类型的显示层
layer = createNormalSurfaceLocked(client, d, id, w, h, flags, format);
}
break;
case eFXSurfaceBlur:
//创建 Blur 类型的显示层
layer = createBlurSurfaceLocked(client, d, id, w, h, flags);
break;
case eFXSurfaceDim:
//创建 Dim 类型的显示层
layer = createDimSurfaceLocked(client, d, id, w, h, flags);
break;
} if(layer != ) {
layer->setName(name);
setTransactionFlags(eTransactionNeeded);
//从显示层对象中取出一个 ISurface 对象赋值给 SurfaceHandle
surfaceHandle = layer->getSurface();
if(surfaceHandle != ) {
params->token = surfaceHandle->getToken();
params->identity = surfaceHandle->getIdentity();
params->width = w;
params->height = h;
params->format = format;
}
}
return surfaceHandle;//ISurface 的 Bn 端就是这个对象
}
sp<LayerBaseClient>SurfaceFlinger::createNormalSurfaceLocked(const sp<Client>& client, DisplayID display, int32_t id, uint32_t w, uint32_t h, uint32_t flags, PixelFormat& format) {
switch(format) { //一些图像方面的参数设置,可以不去管它
case PIXEL_FORMAT_TRANSPARENT:
case PIXEL_FORMAT_TRANSLUCENT:
format = PIXEL_FORMAT_RGBA_8888;
break;
case PIXEL_FORMAT_OPAQUE:
format = PIXEL_FORMAT_RGB_565;
break;
} //创建一个 Layer 类型的对象
sp<Layer> layer = new Layer(this, display,client, id); //设置 Buffer
status_t err = layer->setBuffers(w, h, format, flags);
if (LIKELY(err == NO_ERROR)) {
//初始化这个新 layer 的一些状态
layer->initStates(w, h, flags);
//下面这个函数把这个 layer 加入到 Z 轴集合中
addLayer_l(layer);
}
......
return layer;
}
createNormalSurfaceLocked 函数有三个关键点,它们是:
- 构造一个Layer对象。
- 调用Layer对象的setBuffers函数。
- 调用SF的addLayer_l函数。
当跨进程的 createSurface() 执行完返回一个 ISurface 对象,接下来会创建 SurfaceControl 对象:
SurfaceControl::SurfaceControl(
const sp<SurfaceComposerClient>& client,
const sp<ISurface>& surface,
const ISurfaceFlingerClient::surface_data_t& data,
uint32_t w, uint32_t h, PixelFormat format, uint32_t flags)
//mClient 为 SurfaceComposerClient,而 mSurface 指向跨进程 createSurface() 调用返回的 ISurface 对象
:mClient(client), mSurface(surface),
mToken(data.token), mIdentity(data.identity),
mWidth(data.width), mHeight(data.height), mFormat(data.format),
mFlags(flags){
......
}
SurfaceControl 类可以看作是一个 wrapper 类,它封装了一些函数,通过这些函数可以方便地调用 mClient 或 ISurface 提供的函数。
最后会执行 copyFrom() 返回给 App 客户端:
static void Surface_copyFrom(JNIEnv* env,jobject clazz, jobject other) {
//根据JNI函数的规则,clazz 是 copyFrom 的调用对象,而 other 是 copyFrom 的参数。
//目标对象此时还没有设置 SurfaceControl,而源对象在前面已经创建了 SurfaceControl
constsp<SurfaceControl>& surface = getSurfaceControl(env, clazz);
constsp<SurfaceControl>& rhs = getSurfaceControl(env, other);
if (!SurfaceControl::isSameSurface(surface, rhs)) {
//把源 SurfaceControl 对象设置到目标 Surface 中
setSurfaceControl(env, clazz, rhs);
}
}
copyFrom 期间一共有三个关键对象,它们分别是:
- SurfaceComposerClient
- SurfaceControl
- Surface,这个 Surface 对象属于 Native 层,和 Java 层的 Surface 相对应
其中转移到 ViewRoot 成员变量 mSurface 中的,就是最后这个 Surface 对象了。
在 SurfaceFlinger 进程中,Client 的一个 Layer 将使用 SharedBufferStack 数组中的一个成员,并通过 SharedBufferServer 结构来控制这个成员, SurfaceFlinger 是消费者,所以可由 SharedBufferServer 来控制数据的读取。与之相对应,客户端的进程也会有一个对象来使用这个 SharedBufferStack,可它是通过另外一个叫 SharedBufferClient 的结构来控制的。客户端为 SurfaceFlinger 提供数据,所以可由 SharedBufferClient 控制数据的写入。
Surface 显示过程总结:
如图所示,在 App 进程中创建 PhoneWindow 后会创建 ViewRoot。ViewRoot 的创建会创建一个 Surface,这个 Surface 其实是空的,通过与 WindowManagerService 通信 copyFrom() 一个NativeSurface。在与 SurfaceFlinger 通信时,会创建 SharedClient 一段共享内存,里面存放的是 SharedBufferStack 对应 SurfaceFlinger 中的 SurfaceLayer 每个 Layer 其实是一个 FrameBuffer,每个 FrameBuffer 中有两个 GraphicBuffer 记作 FrontBuffer 和 BackBuffer。
在SurfaceFlinger 中 SharedBufferServer 来管理 FrameBuffer。同时在 App 端 copyFrom() 出来 NativeSurface 时会创建一个 SharedBufferClient 与 SharedClient 这块共享内存关联。当客户端 addView() 或者需要更新 View 时,会通过 SharedBufferClient 写入数据到 ShareClient 中,SurfaceFlinger 中的 SharedBufferServer 接收到通知会将 FrameBuffer 中的数据传输到屏幕上。
5.本地窗口(Native Window)
Native Window为OpenGL与本地窗口系统之间搭建了桥梁。整个GUI系统至少需要两种本地窗口:
(1)面向管理者(SurfaceFlinger)
SurfaceFlinger是系统中所有UI界面的管理者,需要直接或间接的持有“本地窗口”,此本地窗口是FramebufferNativeWindow。
(2)面向应用程序
这类本地窗口是Surface。
正常情况按照SDK向导生成APK应用程序,是采用Skia等第三方图形库,而对于希望使用OpenGL ES来完成复杂界面渲染的应用开发者来说,Android也提供封装的GLSurfaceView(或其他方式)来实现图形显示。
①FramebufferNativeWindow
EGL需要通过本地窗口来为OpenGL/OpenGL ES创建环境。由于OpenGL/ES对多平台支持,考虑到兼容性和移植性。不同平台的本地窗口EGLNativeWindowType数据类型不同。
Android平台的数据类型是ANativeWindow,像是一份“协议”,规定了一个本地窗口的形态和功能。ANativeWindow是FramebufferNativeWindow的父类。
Android中,由于多缓冲技术,EGLNativeWindowType所管理的缓冲区最少2个,最大3个。
FramebufferNativeWindow初始化需要Golloc支持,步骤如下:
- 加载GRALLOC_HARDWARE_MODULE_ID模块,参见上节。
- 分别打开fb和gralloc设备,打开后的设备由全局变量fbDev和grDev管理。
- 根据设备的属性来给FramebufferNativeWindow赋初值。
- 根据FramebufferNativeWindow的实现来填充ANativeWindow中的“协议”
- 其他一些必要的初始化
②应用程序的本地窗口 - Surface
Surface也继承了ANativeWindow
class Surface : public ANativeObjectBase<ANativeWindow, Surface, RefBase>
Surface是面向Android系统中所有UI应用程序的,即它承担着应用进程中的UI显示需求。
需要面向上层实现(主要是Java层)提供绘制图像的画板。SurfaceFlinger需要收集系统中所有应用程序绘制的图像数据,然后集中显示到物理屏幕上。Surface需要扮演相应角色,本质上还是由SurfaceFlinger服务统一管理的,涉及到很多跨进程的通信细节。
③Surface的创建
Surface将通过mGraphicBufferProducer来获取buffer,这些缓冲区会被记录在mSlots中数据中。mGraphicBufferProducer这一核心成员的初始化流程如下:
ViewRootImpl持有一个Java层的Surface对象(mSurface)。
ViewRootImpl向WindowManagerService发起relayout请求,此时mSurface被赋予真正的有效值,将辗转生成的SurfaceControl通过Surface.copyFrom()函数复制到mSurface中。
由此,Surface由SurfaceControl管理,SurfaceControl由SurfaceComposerClient创建。SurfaceComposerClient获得的匿名Binder是ISurfaceComposer,其服务端实现是SurfaceFlinger。而Surface依赖的IGraphicBufferProducer对象在Service端的实现是BufferQueue。
class SurfaceFlinger :
public BinderService<SurfaceFlinger>, //在ServiceManager中注册为SurfaceFlinger
public BnSurfaceComposer,//实现的接口却叫ISurfaceComposer
④SurfaceFlinger服务框架:
Buffer,Consumer,Producer是“生产者-消费者”模型中的3个参与对象,如何协调好它们的工作是应用程序能否正常显示UI的关键。
Buffer是BufferQueue,Producer是应用程序,Consumer是SurfaceFlinger。
Surface内部提供一个BufferQueue,与上层和SurfaceFlinger形成一个生产者消费者模型,上层对应Producer,SurfaceFlinger对应Consumer。三者通过Buffer产生联系,每个Buffer都有四种状态:
- Free:可被上层使用;
- Dequeued:出列,正在被上层使用;
- Queued:入列,已完成上层绘制,等待SurfaceFlinger合成;
- Acquired:被获取,SurfaceFlinger正持有该Buffer进行合成;
如此循环,形成一个Buffer被循环使用的过程(FREE-> DEQUEUED->QUEUED->ACQUIRED->FREE)。
BufferQueue中的mSlots数组用于管理期内的缓冲区,最大容器是32。数据缓冲区的空间是动态分配的,应用程序与SurfaceFlinger都是使用OpenGL ES来完成UI显示。Layer类在SurfaceFlinger中表示“层”,通俗地讲就是代表了一个“画面”,最终物理屏幕上的显示结果就是通过对系统中同时存在的所有“画面”进行处理叠加而成.