SurfaceFlinger 启动流程分析

引言

分析 SurfaceFlinger 的渲染应用程序的 UI 前,首先我们会对 SurfaceFlinger 的启动流程SurfaceFlinger 服务初始化硬件帧缓冲区的过程 以及 SurfaceFlinger服务的线程模型 有一个比较简单的认识,当然有喜欢看源码的朋友建议看下以下几篇文章:

源码基于 Ice Cream Sandwich MR1 | 4.0.4_r2.1 进行分析

SurfaceFlinger 的启动流程

简介

SurfaceFlinger 服务是在 System 进程中启动的,并且负责统一管理设备的帧缓冲区。SurfaceFlinger 服务在启动的过程中,会创建两个线程,其中一个线程用来监控控制台事件,而另外一个线程用来渲染系统的UI。System 进程是由 Zygote 进程启动的,并且是以 Java 层的 SystemServer 类的静态成员函数 main 为入口函数的。启动过程如下图

image.png

SystemServer.class

// 源码位置: https://www.androidos.net.cn/android/4.2.2_r1/xref/frameworks/base/services/java/com/android/server/SystemServer.java

public class SystemServer {
    ...
    /**
     * 这个方法从Zygote被调用来初始化系统。
     * 这将导致本地服务(SurfaceFlinger, AudioFlinger等)启动。
     * 之后,它会回调init2()来启动Android服务
     */
    native public static void init1(String[] args);
    public static void main(String[] args) {
        ...
        System.loadLibrary("android_servers");
        init1(args);
    }
    public static final void init2() {
        Slog.i(TAG, "Entered the Android system server!");
        Thread thr = new ServerThread();
        thr.setName("android.server.ServerThread");
        thr.start();
    }
}
复制代码

这个类就没啥可说的,入口函数 main 中加载了 android_servers 系统服务 so 并且调用了 native 的 init1 的初始化方法,及 com_android_server_SystemServer.cpp 中的 android_server_SystemServer_init1

namespace android {
   
    extern "C" int system_init();

static void android_server_SystemServer_init1(JNIEnv* env, jobject clazz)
    {
    system_init();
    }

/*
 * JNI registration.
 */
static JNINativeMethod gMethods[] = {
    /* name, signature, funcPtr */
    { "init1", "([Ljava/lang/String;)V", (void*) android_server_SystemServer_init1 },
    };

    int register_android_server_SystemServer(JNIEnv* env)
    {
    return jniRegisterNativeMethods(env, "com/android/server/SystemServer",
    gMethods, NELEM(gMethods));
    }

}; // namespace android
复制代码

当然,可能有的盆友对 jni 不是很了解,这边稍微解释下是如何调用过来的。调用 jni 分为两种一种是静态注册,另外一种是动态注册。

jni 静态注册

这是一个 FmodActivity 类,这个类中有一个 playVoicenative 方法,

package com.testndk.jnistudy.ui.activity;

public class FmodActivity extends BaseActivity {
    public native void playVoice(int model, String path);
}
复制代码

当你写完该方法,编译器会提示报错,你可以通过编译器在 c 文件生成以下固定格式的代码 Java_包名_类名_方法名,当然前提是你得项目支持 c++,这边不做过多讲解了。也可以通过 javah -jni 的指令生成,这个就自行百度。

Java_com_testndk_jnistudy_ui_activity_FmodActivity_playVoice(JNIEnv *env, jobject thiz, jint model,
                                                             jstring file_path_) {}
复制代码

这种情况就属于静态注册

jni 动态注册

这个可以看 SystemServer 类,他也有一个 native 的方法 init1

native public static void init1(String[] args);
复制代码

但是我们可以从 com_android_server_SystemServer 中没有找到类似于静态方法那样的代码格式,而是

扫描二维码关注公众号,回复: 14247589 查看本文章
/*
 * JNI registration.
 */
static JNINativeMethod gMethods[] = {
    /* name, signature, funcPtr */
    { "init1", "([Ljava/lang/String;)V", (void*) android_server_SystemServer_init1 },
    };

    int register_android_server_SystemServer(JNIEnv* env)
    {
    return jniRegisterNativeMethods(env, "com/android/server/SystemServer",
    gMethods, NELEM(gMethods));
    }
复制代码

gMethods[] 的方式进行注册的。

这里就是 静态注册 和 动态注册的区别,至于优缺点这里不做过多的讨论,回归 SurfaceFlinger 启动的主流程

android_server_SystemServer_init1 中,调用了 system_init 的方法,可能看到这里的朋友都不知道这个 system_init 方法那里来的,看到下面这句代码就应该知道什么意思了

extern "C" int system_init();
复制代码

接着我们找到这个方法

// https://www.androidos.net.cn/android/4.0.4_r2.1/xref/frameworks/base/cmds/system_server/library/system_init.cpp

extern "C" status_t system_init()
    {
        LOGI("Entered system_init()");

        sp<ProcessState> proc(ProcessState::self());
        ......

        char propBuf[PROPERTY_VALUE_MAX];
        property_get("system_init.startsurfaceflinger", propBuf, "1");
        if (strcmp(propBuf, "1") == 0) {
            // Start the SurfaceFlinger  
            SurfaceFlinger::instantiate();
        }

        ......

        if (proc->supportsProcesses()) {
            LOGI("System server: entering thread pool.\n");
            ProcessState::self()->startThreadPool();
            IPCThreadState::self()->joinThreadPool();
            LOGI("System server: exiting thread pool.\n");
        }
        return NO_ERROR;
    } 
复制代码

函数首先获得 System 进程中的一个 ProcessState 单例,并且保存在变量 proc 中,后面会通过调用它的成员函数 supportsProcesses 来判断系统是否支持 Binder进程间通信机制。函数接下来就检查系统中是否存在一个名称为 system_init.startsurfaceflinger 的属性。如果存在的话,就将它的值获取回来,并且保存在缓冲区 proBuf 中。如果不存在的话,那么函数 property_get 就会将缓冲区 proBuf 的值设置为 1。当缓冲区 proBuf 的值等于 1 的时候,就表示需要在 System 进程中将 SurfaceFlinger 服务启动起来,这是通过调用 SurfaceFlinger 类的静态成员函数 instantiate 来实现的。

函数最后检查系统是否支持 Binder 进程间通信机制。如果支持的话,那么接下来就会调用当前进程中的ProcessState 单例的成员函数 startThreadPool 来启动一个 Binder 线程池,并且调用当前线程中的IPCThreadState 单例来将当前线程加入到前面所启动的 Binder 线程池中去。有了这个 Binder 线程池之后,SurfaceFlinger 服务在启动完成之后,就可以为系统中的其他组件或者进程提供服务了。

这里我们假设 system_init.startsurfaceflinger 属性的值为 1,以便于走 SurfaceFlinger 初始化流程

// https://www.androidos.net.cn/android/4.0.4_r2.1/xref/frameworks/base/services/surfaceflinger/SurfaceFlinger.h
class SurfaceFlinger : 
    public BinderService<SurfaceFlinger>, 
    public BnSurfaceComposer,
    private IBinder::DeathRecipient,
    private Thread,
    private HWComposer::EventHandler {
        ...
    }
复制代码

这边我们可以看到 SurfaceFlinger 继承自 BinderService,并且 SurfaceFlinger.cpp 中并没有 instantiate 方法的实现(SurfaceFlinger.cpp),只能从父类中找 instantiate 的实现

BinderService.h

// https://www.androidos.net.cn/android/4.0.4_r2.1/xref/frameworks/base/include/binder/BinderService.h
class BinderService
{
    public:
    static status_t publish() { 
        sp<IServiceManager> sm(defaultServiceManager());
        return sm->addService(String16(SERVICE::getServiceName()), new SERVICE()); 
    }
    
    ...
    
    static void instantiate() { publish(); }
    
    ...
};
复制代码

BinderService 类的静态成员函数 instantiate 的实现很简单,它只是调用 BinderService 类的另外一个静态成员函数 publish 来继续执行启动 SurfaceFlinger 服务的操作。

BinderService 是一个模板类,它有一个模板参数 SERVICE。当 BinderService 类被SurfaceFlinger 类继承时,模板参数 SERVICE 的值就等于 SurfaceFlinger。因此,BinderService 类的静态成员函数 publish 所执行的操作就是创建一个 SurfaceFlinger 实例,用来作为系统的 SurfaceFlinger 服务。

SurfaceFlinger.cpp

// https://www.androidos.net.cn/android/4.0.4_r2.1/xref/frameworks/base/services/surfaceflinger/SurfaceFlinger.cpp
SurfaceFlinger::SurfaceFlinger()
        :   BnSurfaceComposer(), Thread(false),
        ...
        {
        init();
        }

void SurfaceFlinger::init()
        {
        LOGI("SurfaceFlinger is starting");

        // debugging stuff...
        char value[PROPERTY_VALUE_MAX];

        property_get("debug.sf.showupdates", value, "0");
        mDebugRegion = atoi(value);

        property_get("debug.sf.showbackground", value, "0");
        mDebugBackground = atoi(value);

        property_get("debug.sf.ddms", value, "0");
        mDebugDDMS = atoi(value);
        if (mDebugDDMS) {
        DdmConnection::start(getServiceName());
        }

        LOGI_IF(mDebugRegion,       "showupdates enabled");
        LOGI_IF(mDebugBackground,   "showbackground enabled");
        LOGI_IF(mDebugDDMS,         "DDMS debugging enabled");
        }
复制代码

并且将这个服务 addServiceService Manager 中去,这样系统中的其它组件或者进程就可以通过 Service Manager 来获得 SurfaceFlinger 服务的 Binder 代理对象,进而使用它所提供的服务。

由于 Service ManagerBinder 代理对象的成员函数 addService 的第二个参数是一个类型为IBinder的强指针引用。从 Android系统的智能指针(轻量级指针、强指针和弱指针)的实现原理可以得知,当一个对象第一次被一个强指针引用时,那么这个对象的成员函数 onFirstRef 就会被调用。

// https://www.androidos.net.cn/android/4.0.4_r2.1/xref/frameworks/base/services/surfaceflinger/SurfaceFlinger.cpp#210

void SurfaceFlinger::onFirstRef() {
        run("SurfaceFlinger", PRIORITY_URGENT_DISPLAY);
        // Wait for the main thread to be done with its initialization 
        mReadyToRunBarrier.wait(); 
    }
复制代码

函数首先调用从父类继承下来的成员函数 run 来启动一个名秒为 SurfaceFlinger 的线程,用来执行 UI 渲染操作。这就是前面我们所说的 UI 渲染线程了。这个UI渲染线程创建完成之后,首先会调用 SurfaceFlinger 类的成员函数 readyToRun 来执行一些初始化操作,接着再循环调用 SurfaceFlinger 类的成员函数 threadLoop 来作为线程的执行体。

mReadyToRunBarrierSurfaceFlinger 类的一个成员变量,它的类型是 Barrier,用来描述一个屏障,是通过条件变量来实现的。我们可以把它看作是一个线程同步工具,即阻塞当前线程,直到 SurfaceFlinger 服务的 UI 渲染线程执行完成初始化操作为止。

我们就继续分析 SurfaceFlinger 类的成员函数 readyToRun 的实现,以便可以了解 SurfaceFlinger 服务的 UI 渲染线程的初始化过程。

// https://www.androidos.net.cn/android/4.0.4_r2.1/xref/frameworks/base/services/surfaceflinger/SurfaceFlinger.cpp#223
status_t SurfaceFlinger::readyToRun()
        {
        LOGI(   "SurfaceFlinger's main thread ready to run. "
        "Initializing graphics H/W...");

        // we only support one display currently
        int dpy = 0;

        {
        // initialize the main display
        // 首先创建了一个 DisplayHardware 对象 hw,用来描述设备的显示屏,并且用这个 DisplayHardware
        // 对象来初始化 SurfaceFlinger 类的成员变量 mGraphicPlanes 所描述的一个 GraphicPlane 数组的第一个元素。
        // 在 DisplayHardware 对象 hw 的创建过程中,会创建另外一个线程,用来监控控制台事件,
        // 即监控硬件帧缓冲区的睡眠和唤醒事件。
        GraphicPlane& plane(graphicPlane(dpy));
        DisplayHardware* const hw = new DisplayHardware(this, dpy);
        plane.setDisplayHardware(hw);
        }

        // create the shared control-block
        // 创建了一块大小为 4096,即 4KB 的匿名共享内存,接着将这块匿名共享内存结构化为一个
        // surface_flinger_cblk_t 对象来访问。这个 surface_flinger_cblk_t 对象就保存在 SurfaceFlinger 
        // 类的成员变量 mServerCblk 中。这块匿名共享内存用来保存设备显示屏的属性信息,
        // 例如,宽度、高度、密度和每秒多少帧等信息
        mServerHeap = new MemoryHeapBase(4096,
        MemoryHeapBase::READ_ONLY, "SurfaceFlinger read-only heap");
        LOGE_IF(mServerHeap==0, "can't create shared memory dealer");

        mServerCblk = static_cast<surface_flinger_cblk_t*>(mServerHeap->getBase());
        LOGE_IF(mServerCblk==0, "can't get to shared control block's address");

        new(mServerCblk) surface_flinger_cblk_t;

        // initialize primary screen
        // (other display should be initialized in the same manner, but
        // asynchronously, as they could come and go. None of this is supported
        // yet).
        // 这段代码首先获得 SurfaceFlinger 类的成员变量 mGraphicPlanes 所描述的一个 GraphicPlane 
        // 数组的第一个元素 plane,接着再设置它的宽度、长度和像素格式等作息,最后再调用它里面的一个
        // DisplayHardware 对象 hw 的成员函数 makeCurrent 来将它作为系统的主显示屏。
        // 这个 DisplayHardware 对象 hw 是在前面第一段代码中创建的,在创建的过程中,它会执行一些初始化操作,
        // 这里将它设置为系统主显示屏之后,后面就可以将系统的UI渲染在它上面了。
        const GraphicPlane& plane(graphicPlane(dpy));
        const DisplayHardware& hw = plane.displayHardware();
        const uint32_t w = hw.getWidth();
        const uint32_t h = hw.getHeight();
        const uint32_t f = hw.getFormat();
        hw.makeCurrent();

        // initialize the shared control block
        // 这段代码将系统主显示屏的属性信息保存在前面所创建的一块匿名共享内存中,
        // 以便可以将系统主显示屏的属性信息返回给系统中的其它进程访问。
        mServerCblk->connected |= 1<<dpy;
        display_cblk_t* dcblk = mServerCblk->displays + dpy;
        memset(dcblk, 0, sizeof(display_cblk_t));
        dcblk->w            = plane.getWidth();
        dcblk->h            = plane.getHeight();
        dcblk->format       = f;
        dcblk->orientation  = ISurfaceComposer::eOrientationDefault;
        dcblk->xdpi         = hw.getDpiX();
        dcblk->ydpi         = hw.getDpiY();
        dcblk->fps          = hw.getRefreshRate();
        dcblk->density      = hw.getDensity();

        // Initialize OpenGL|ES
        // 这段代码用来初始化 OpenGL 库,因为 SurfaceFlinger 服务是通过 OpenGL 库提供的 API 来渲染系统的 UI 的。
        glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
        glPixelStorei(GL_PACK_ALIGNMENT, 4);
        glEnableClientState(GL_VERTEX_ARRAY);
        glEnable(GL_SCISSOR_TEST);
        glShadeModel(GL_FLAT);
        glDisable(GL_DITHER);
        glDisable(GL_CULL_FACE);

        const uint16_t g0 = pack565(0x0F,0x1F,0x0F);
        const uint16_t g1 = pack565(0x17,0x2f,0x17);
        const uint16_t wormholeTexData[4] = { g0, g1, g1, g0 };
        glGenTextures(1, &mWormholeTexName);
        glBindTexture(GL_TEXTURE_2D, mWormholeTexName);
        glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
        glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
        glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
        glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 2, 2, 0,
        GL_RGB, GL_UNSIGNED_SHORT_5_6_5, wormholeTexData);

        const uint16_t protTexData[] = { pack565(0x03, 0x03, 0x03) };
        glGenTextures(1, &mProtectedTexName);
        glBindTexture(GL_TEXTURE_2D, mProtectedTexName);
        glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
        glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
        glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
        glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1, 1, 0,
        GL_RGB, GL_UNSIGNED_SHORT_5_6_5, protTexData);

        glViewport(0, 0, w, h);
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        // put the origin in the left-bottom corner
        glOrthof(0, w, 0, h, 0, 1); // l=0, r=w ; b=0, t=h
        // SurfaceFlinger 服务的 UI 渲染线程已经创建并且初始化完成了,
        // 这时候 System 进程的主线程就可以继续向前执行其它操作了。
        mReadyToRunBarrier.open();

        /*
         *  We're now ready to accept clients...
         */

        // start boot animation
        // 调用函数 property_set 来设置系统中名称为 “ctl.start” 的属性,即将它的值设置为“bootanim”。
        // 当它的值等于 “bootanim” 的时候,就表示要启动 Android 系统的开机动画。
        property_set("ctl.start", "bootanim");

        return NO_ERROR;
        }
复制代码

从这里就可以看出,当我们看到 Android 系统的开机动画时,就说明 Android 系统的 SurfaceFlinger 服务已经启动起来了。至此,我们就分析完成 SurfaceFlinger 服务的启动过程了。

猜你喜欢

转载自juejin.im/post/7106690797793181726
今日推荐