SurfaceFlinger学习笔记(三)之SurfaceFlinger进程

概述

本系列是基于android Q 即android10
SurfaceFlinger学习笔记(一)应用启动流程
SurfaceFlinger学习笔记(二)之Surface
SurfaceFlinger学习笔记(三)之SurfaceFlinger进程
SurfaceFlinger学习笔记(四)之HWC2
SurfaceFlinger学习笔记(五)之HWUI
SurfaceFlinger学习笔记(六)之View Layout Draw过程分析

android底层用到了许多C++11,参考C++11简介

在Android中,一个窗口用一个Surface描述。多个窗口(窗口不一定都是Activity),需要同时显示,我们就需要将多个窗口进行合并。这就需要显示系统中重量级的服务SurfaceFlinger,Surfaceflinger控制窗口的合成,将多个窗口合并成一个,再送到LCD

在这里插入图片描述
在这里插入图片描述

SurfaceFlinger合成,有两种方式,Client和Device。Client就是Client合成完Layer后再将合成后的数据给到HWComposer,HWComposer此时做的工作很少,直接给到Display。Device则是将未合成的Layer,给到硬件合成的设备,合成完后再给到Display

应用启动流程回顾

详细流程参考
SurfaceFlinger学习笔记(一)应用启动流程
SurfaceFlinger学习笔记(二)之Surface和HWUI

  1. Activity::startActivityForResult调用mInstrumentation.execStartActivity调用ActivityManager.getService().startActivity
  2. ActivityManagerService::startActivityAsUser调用ActivityStartController.obtainStarter调用ActivityStarter.execute调用ActivityStarter.startActivityMayWait
    ActivityStarter.startActivityUnchecked(这个方法里会根据启动标志位和Activity启动模式来决定如何启动一个Activity以及是否要调用deliverNewIntent方法通知Activity有一个Intent试图重新启动它)
  3. ActivityStackSupervisor.resumeFocusedStackTopActivityLocked调用ActivityStack.resumeTopActivityInnerLocked
  4. 在ActivityStack.resumeTopActivityInnerLocked方法中会去判断是否有Activity处于Resume状态,如果有的话会先让这个Activity执行Pausing过程,然后再执行startSpecificActivityLocked方法启动要启动Activity

栈顶Activity执行onPause方法退出流程
frameworks/base/services/core/java/com/android/server/am/ActivityStack.java

  1. 在ActivityStack.startPausingLocked方法中通过ClientLifecycleManager的scheduleTransaction方法把PauseActivityItem事件加入到执行计划中,开始栈顶的pausing过程,然后执行ClientTransaction.schedule,ClientTransaction.schedule方法的mClient是一个IApplicationThread类型,ActivityThread的内部类ApplicationThread派生这个接口类并实现了对应的方法。所以直接跳转到ApplicationThread中的scheduleTransaction方法。ActivityThread类中并没有定义scheduleTransaction方法,所以调用的是他父类ClientTransactionHandler的scheduleTransaction方法
  2. 在ClientTransactionHandler.scheduleTransaction方法中调用了sendMessage方法,这个方法是一个抽象方法,其实现在ClientTransactionHandler派生类的ActivityThread中,ActivityThread.sendMessage方法会把消息发送给内部名字叫H的Handler
  3. Handler H的实例接收到EXECUTE_TRANSACTION消息后调用TransactionExecutor.execute方法切换Activity状态。TransactionExecutor.execute方法里面先执行Callbacks,然后改变Activity当前的生命周期状态。此处由于没有Callback所以直接跳转executeLifecycleState方法。
  4. 在executeLifecycleState方法里面,会先去调用TransactionExecutor.cycleToPath执行当前生命周期状态之前的状态,然后执行ActivityLifecycleItem.execute方法。由于是从ON_RESUME状态到ON_PAUSE状态切换,中间没有其他状态,cycleToPath这个情况下没有做什么实质性的事情,直接执行execute方法。前面在ActivityStack.startPausingLocked方法里面scheduleTransaction传递的是PauseActivityItem对象,所以executeLifecycleState方法里调用的execute方法其实是PauseActivityItem.execute方法。
  5. 在PauseActivityItem.execute方法中调用ActivityThread.handlePauseActivity方法,经过一步步调用来到performPauseActivity方法,在这个方法中会先去判断是否需要调用callActivityOnSaveInstanceState方法来保存临时数据,然后执行Instrumentation.callActivityOnPause方法继续执行pasue流程。
  6. Instrumentation.callActivityOnPause方法中直接调用Activity.performPause

Activity所在的应用进程启动过程

  1. ActivityStackSupervisor.startSpecificActivityLocked方法,在这个方法中会去根据进程和线程是否存在判断App是否已经启动,如果已经启动,就会调用realStartActivityLocked方法继续处理。如果没有启动则调用ActivityManagerService.startProcessLocked方法创建新的进程处理。接下来跟踪一下一个新的Activity是如何一步步启动的。
  2. ActivityManagerService.startProcessLocked方法经过多次跳转最终会通过Process.start方法来为应用创建进程。经过一步步调用,可以发现其最终调用了Zygote并通过socket通信的方式让Zygote进程fork出一个新的进程,并根据传递的”android.app.ActivityThread”字符串,反射出该对象并执行ActivityThread的main方法对其进行初始化
  3. 在ActivityThread.main方法中对ActivityThread进行了初始化,创建了主线程的Looper对象并调用Looper.loop()方法启动Looper,把自定义Handler类H的对象作为主线程的handler。接下来跳转到ActivityThread.attach方法
  4. 在ActivityThread.attach方法中,首先会通过ActivityManagerService为这个应用绑定一个Application,然后添加一个垃圾回收观察者,每当系统触发垃圾回收的时候就会在run方法里面去计算应用使用了多少内存,如果超过总量的四分之三就会尝试释放内存。最后,为根View添加config回调接收config变化相关的信息
  5. 在ActivityManagerService.attachApplication方法中经过多次跳转执行到ActivityStackSupervisor.attachApplicationLocked调用ActivityStackSupervisor.realStartActivityLocked方法。在ActivityStackSupervisor.realStartActivityLocked方法中为ClientTransaction对象添加LaunchActivityItem的callback,然后设置当前的生命周期状态,最后调用ClientLifecycleManager.scheduleTransaction方法执行
  6. 调用ClientLifecycleManager.scheduleTransaction方法之后具体是如何执行的前面已经分析过了,这里就不再分析了。callback后跳转到LaunchActivityItem.execute,然后执行到ActivityThread.handleLaunchActivity
  7. 在ActivityThread.performLaunchActivity方法中首先对Activity的ComponentName、ContextImpl、Activity以及Application对象进行了初始化并相互关联,然后设置Activity主题,最后调用Instrumentation.callActivityOnCreate方法。
  8. 从Instrumentation.callActivityOnCreate方法继续追踪,跳转到Activity.performCreate方法,在这里我们看到了Activity.onCreate方法。
  9. 至此executeCallbacks执行完毕,开始执行executeLifecycleState方法。先执行cycleToPath方法,生命周期状态是从ON_CREATE状态到ON_RESUME状态,中间有一个ON_START状态,所以会执行ActivityThread.handleStartActivity方法。
    10 . 执行完毕cycleToPath,开始执行ResumeActivityItem.execute方法。经过上面的多次跳转最终调用到Activity.onResume方法,Activity启动完毕。

Surface相关的基础知识介绍

在这里插入图片描述

  • 显示层(Layer)和屏幕组成
    在这里插入图片描述
  • 屏幕位于一个三维坐标系中,其中Z轴从屏幕内指向屏幕外
  • 编号为①②③的矩形块叫显示层(Layer)。每一层有自己的属性,例如颜色、透明度、所处屏幕的位置、宽、高等。除了属性之外,每一层还有自己对应的显示内容,也就是需要显示的图像。
  • 在Android中,Surface系统工作时,会由SurfaceFlinger对这些按照Z轴排好序的显示层进行图像混合,混合后的图像就是在屏幕上看到的美妙画面了

Surface系统提供了三种属性,一共四种不同的显示层

  • 第一种属性是eFXSurfaceNormal属性,大多数的UI界面使用的就是这种属性。它有两种模式:
    1)Normal模式,这种模式的数据,是通过前面的mView.draw(canvas)画上去的。这也是绝大多数UI所采用的方式。
    2)PushBuffer模式,这种模式对应于视频播放、摄像机摄录/预览等应用场景。以摄像机为例,当摄像机运行时,来自Camera的预览数据直接push到Buffer中,无须应用层自己再去draw了。
  • 第二种属性是eFXSurfaceBlur属性,这种属性的UI有点朦胧美,看起来很像隔着一层毛玻璃。
  • 第三种属性是eFXSurfaceDim属性,这种属性的UI看起来有点暗,好像隔了一层深色玻璃。从视觉上讲,虽然它的UI看起来有点暗,但并不模糊。而eFXSurfaceBlur不仅暗,还有些模糊。

关于Surface系统的显示层属性定义,读者可参考ISurfaceComposer.h

PageFlipping

PageFlipping的中文名叫画面交换,其操作过程如下所示:

  • 分配一个能容纳两帧数据的缓冲,前面一个缓冲叫FrontBuffer,后面一个缓冲叫BackBuffer。
  • 消费者使用FrontBuffer中的旧数据,而生产者用新数据填充BackBuffer,二者互不干扰。
  • 当需要更新显示时,BackBuffer变成FrontBuffer,FrontBuffer变成BackBuffer。如此循环,这样就总能显示最新的内容了。这个过程很像我们平常的翻书动作,所以它被形象地称为PageFlipping。
    说白了,PageFlipping其实就是使用了一个只有两个成员的帧缓冲队列,以后在分析数据传输的时候还会见到诸如dequeue和queue的操作

图像混合

Surface系统支持软硬两个层面的图像混合

  • 软件层面的混合:例如使用copyBlt进行源数据和目标数据的混合
  • 硬件层面的混合:使用Overlay系统提供的接口
    无论是硬件还是软件层面,都需将源数据和目标数据进行混合,混合需考虑很多内容,例如源的颜色和目标的颜色叠加后所产生的颜色

copyBlt和Overlay

  • copyBlt,从名字上看,是数据拷贝,它也可以由硬件实现,例如现在很多的2D图形加速就是将copyBlt改由硬件来实现,以提高速度的。但不必关心这些,我们只需关心如何调用copyBlt相关的函数进行数据混合即可
  • Overlay方法必须有硬件支持才可以,它主要用于视频的输出,例如视频播放、摄像机摄像等,因为视频的内容往往变化很快,所以如改用硬件进行混合效率会更高

应用进程

  1. 应用进程的SurfaceSession 的创建会调用 JNI,在 JNI 调用 nativeCreate,创建 SurfaceComposerClient 对象, 作为跟 SurfaceFlinger 通信的代理对象
* frameworks/base/core/jni/android_view_SurfaceSession.cpp
static jlong nativeCreate(JNIEnv* env, jclass clazz) {
   
   
    SurfaceComposerClient* client = new SurfaceComposerClient();
    client->incStrong((void*)nativeCreate);
    return reinterpret_cast<jlong>(client);
}

* frameworks/native/libs/gui/SurfaceComposerClient.cpp
void SurfaceComposerClient::onFirstRef() {
   
   
	//getComposerService() 将返回 SF 的 Binder 代理端的 BpSurfaceFlinger 对象
	sp<ISurfaceComposer> sf(ComposerService::getComposerService());
    if (sf != nullptr && mStatus == NO_INIT) {
   
   
        sp<ISurfaceComposerClient> conn;
        //先调用 SF 的 createConnection()
        conn = sf->createConnection();
        if (conn != nullptr) {
   
   
            mClient = conn;
            mStatus = NO_ERROR;
        }
    }
}

ComposerService:
定义:frameworks\native\include\private\gui\ComposerService.h
实现:frameworks\native\libs\gui\SurfaceComposerClient.cpp
作用:通过Singleton,定义单例类,初始化时候调用connectLocked,获取SurfaceFlinger服务代理ISurfaceComposer,并注册死亡通知

SurfaceComposerClient:
定义:frameworks\native\include\gui\SurfaceComposerClient.h
实现:frameworks\native\libs\gui\SurfaceComposerClient.cpp
作用:这个对象会和SurfaceFlinger进行交互,因为SurfaceFlinger派生于SurfaceComposer
通过ComposerService和服务端通信,并通过调用binder的createConnection获取ISurfaceComposerClient
onFirstRef:第一次引用的时候,调用binder的createConnection才真正的建立连接,向服务端创建一个ISurfaceComposerClient类型的mClient,负责和服务端通信

  1. java层的SurfaceControl在构造时调用jni方法,nativeCreate,传递一个SurfaceSession,然后通过SurfaceSession 获取SurfaceComposerClient,SurfaceSession 的创建会调用 JNI,在 JNI 调用 SurfaceSession.nativeCreate,创建 SurfaceComposerClient 对象, 作为跟 SurfaceFlinger 通信的代理对象,然后调用SurfaceComposerClient.createSurfaceChecked创建一个native层的SurfaceControl
* frameworks/base/core/jni/android_view_SurfaceControl.cpp
static jlong nativeCreate(JNIEnv* env, jclass clazz, jobject sessionObj ...) {
   
   
    sp<SurfaceComposerClient> client;
    if (sessionObj != NULL) {
   
   
        client = android_view_SurfaceSession_getClient(env, sessionObj);
    } else {
   
   
        client = SurfaceComposerClient::getDefault();//调用内部类DefaultComposerClient创建一个单例SurfaceComposerClient
    }
    SurfaceControl *parent = reinterpret_cast<SurfaceControl*>(parentObject);
    sp<SurfaceControl> surface;
    LayerMetadata metadata;
    Parcel* parcel = parcelForJavaObject(env, metadataParcel);
    if (parcel && !parcel->objectsCount()) {
   
   
        status_t err = metadata.readFromParcel(parcel);
        ...
    }
    status_t err = client->createSurfaceChecked(
            String8(name.c_str()), w, h, format, &surface, flags, parent, std::move(metadata));
   	...
    surface->incStrong((void *)nativeCreate);
    return reinterpret_cast<jlong>(surface.get());
}

* frameworks/native/libs/gui/SurfaceComposerClient.cpp
void SurfaceComposerClient::onFirstRef() {
   
   
    sp<ISurfaceComposer> sf(ComposerService::getComposerService());
    if (sf != nullptr && mStatus == NO_INIT) {
   
   
        sp<ISurfaceComposerClient> conn;
        conn = sf->createConnection();
        if (conn != nullptr) {
   
   
            mClient = conn;
            mStatus = NO_ERROR;
        }
    }
}
status_t SurfaceComposerClient::createSurfaceChecked(const String8& name, uint32_t w, uint32_t h,PixelFormat format,sp<SurfaceControl>* outSurface, uint32_t flags,SurfaceControl* parent,LayerMetadata metadata) {
   
   
   ...
   err = mClient->createSurface(name, w, h, format, flags, parentHandle, std::move(metadata),
                                     &handle, &gbp);
       
   if (err == NO_ERROR) {
   
   
       *outSurface = new SurfaceControl(this, handle, gbp, true /* owned */);
    }
    return err;
}

这里和服务端通信的接口有和ISurfaceComposer.createConnection

SurfaceFlinger进程

进程启动:

SurfaceFlinger是一个系统级的服务,Android系统启动的过程中就会启动SurfaceFlinger,通过init.rc配置bin启动,然后调用到main_surfaceflinger的main中,然后通过surfaceflinger::createSurfaceFlinger进入到SurfaceFlingerFactory启动SurfaceFlinger主服务,并调用init
SurfacFlinger进程中主要4个服务:

  • startGraphicsAllocatorService主要是启动allocator
  • DisplayService,主要负责DisplayEvent的处理,在main_surfaceflinger中启动
  • SurfaceFlinger,主要显示相关的,最重要的服务

在这里插入图片描述

Client和SurfaceFlinger的关系:
在这里插入图片描述
应用端SurfaceComposerClient通过接口ISurfaceComposerClient和SurfaceFlinger的Client建立联系。
服务端创建Client后,把指针返回给应用端,并保存为ISurfaceComposerClient。
应用端通过的ComposerService通过ISurfaceComposer和SurfaceFlinger建立联系。

  1. SurfaceFlinger初始化流程
  • onFirstRef中创建了自己的消息队列mEventQueue,SurfaceFlinger的消息队列
  • 启动EventThread,主要是用以处理和分发Vsync。调用mScheduler的createConnection函数创建的,它的名字是"app"
  • 初始化了Client合成模式(GPU)合成时,需要用到的RenderEngine
  • 初始化HWComposer,注册回调接口registerCallback,HAL会回调一些方法。
  • 如果是VR模式,创建mVrFlinger
  • 创建mEventControlThread,处理Event事件,如Vsync事件和hotplug事件。
  • 初始化显示设备initializeDisplays
* frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
void SurfaceFlinger::init() {
   
   
	 mAppConnectionHandle = mScheduler->createConnection("app", mPhaseOffsets->getCurrentAppOffset(), resyncCallback, impl::EventThread::InterceptVSyncsCallback());
    mSfConnectionHandle = mScheduler->createConnection("sf", mPhaseOffsets->getCurrentSfOffset(),  resyncCallback, 
    								[this](nsecs_t timestamp) {
   
   
                                    mInterceptor->saveVSyncEvent(timestamp);  });

    mEventQueue->setEventConnection(mScheduler->getEventConnection(mSfConnectionHandle));
    mVsyncModulator.setSchedulerAndHandles(mScheduler.get(), mAppConnectionHandle.get(),  mSfConnectionHandle.get());
    ...
    renderEngineFeature |= (useColorManagement ? renderengine::RenderEngine::USE_COLOR_MANAGEMENT : 0);
    renderEngineFeature |= (useContextPriority ? renderengine::RenderEngine::USE_HIGH_PRIORITY_CONTEXT : 0);
    renderEngineFeature |= (enable_protected_contents(false) ? renderengine::RenderEngine::ENABLE_PROTECTED_CONTEXT : 0);

    // TODO(b/77156734): We need to stop casting and use HAL types when possible.
    // Sending maxFrameBufferAcquiredBuffers as the cache size is tightly tuned to single-display.
    mCompositionEngine->setRenderEngine(
            renderengine::RenderEngine::create(static_cast<int32_t>(defaultCompositionPixelFormat),renderEngineFeature, maxFrameBufferAcquiredBuffers));

    LOG_ALWAYS_FATAL_IF(mVrFlingerRequestsDisplay, "Starting with vr flinger active is not currently supported.");
    mCompositionEngine->setHwComposer(getFactory().createHWComposer(getBE().mHwcServiceName));
    mCompositionEngine->getHwComposer().registerCallback(this, getBE().mComposerSequenceId);
     // Process any initial hotplug and resulting display changes.
    processDisplayHotplugEventsLocked();
    ..
    // initialize our drawing state
    mDrawingState = mCurrentState;

    // set initial conditions (e.g. unblank default device)
    initializeDisplays();
    ...
}

EventThread

EventThread并不是一个线程,它的内部有一个线程,这个线程就是用来处理底层Vsync的接收以及分发的,这个线程是一个死循环,当它没收到事件请求时会通过C++条件变量调用wait陷入等待状态
应用层请求Vsync的过程其实就是通过这个条件变量调用notify唤醒EventThread内部这个线程,然后从mPendingEvents中获取到Vsync信息分发给感兴趣的进程

Scheduler.createConnection

  • createConnection这个函数在SurfaceFlinger中调用了两次,一次是创建"app"的Connection,一次是创建"sf"的Connection,我们可以理解为创建两套连接,一套给app使用,一套个surfaceFlinger使用,两套连接的用connectionName以及id进行标识,(id为0,connectionName等于”app“的)与(id为1,connectionName等于”sf“的)
  • createConnection函数根据connectionName创建EventThread,根据EventThread创建EventThreadConnection,然后创建ConnectionHandle,根据ConnectionHandle,EventThreadConnection,EventThread最终创建Connection,并以id为key,Connection为value加入到mConnections的map中,最终返回”app“的ConnectionHandle

EventThreadConnection

继承BnDisplayEventConnection,为DisplayEvent的服务端,构造函数中最重要的就是创建了mChannel,mChannel是gui::BitTube类型
EventThreadConnection代表应用层到SurfaceFlinger进程的连接,每一个上层的ViewRootImpl都对应一个EventThreadConnection,因为每个View视图都需要Vsync来开启绘制工作

gui::BitTube

gui::BitTube的构造函数:这里传递的DefaultSize为4kb,定义在DEFAULT_SOCKET_BUFFER_SIZE
BitTube的init函数主要是通过socketpair函数创建一对socket,socketpair()函数用于创建一对无名的、相互连接的socket,如果成功,则返回0,创建好的socket分别是sv[0]和sv[1];否则返回-1

  1. 这对socket可以用于全双工通信,每一个socket既可以读也可以写。例如,可以往sv[0]中写,从sv[1]中读,或者从sv[1]中写,从sv[0]中读
  2. 如果往一个socket(如sv[0])中写入后,再从该socket读时会阻塞,只能在另一个socket中(sv[1])上读成功
  3. 读、写操作可以位于同一个进程,也可以分别位于不同的进程
    通过socketpair创建好了一对socket之后,再通过setsockopt对socket进行设置,再调用fcntl函数针对socket描述符提供控制

首先应用层想要绘制UI,则需要向native层注册接收下一个到来的Vsync,注册的过程是通过EventThreadConnection的Bp端最终调用到SurfaceFlinger进程的EventThread的requestNextVsync函数

* frameworks/native/services/surfaceflinger/Scheduler/Scheduler.cpp
sp<Scheduler::ConnectionHandle> Scheduler
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值