flutter-elinux启动流程解读

1 使用bundle资源路径构造flutter::DartProject对象 1 1 bundle资源路径下需要 data flutter_assets, data icudtl dat, lib libapp

1. 使用bundle资源路径构造flutter::DartProject对象
    1.1 bundle资源路径下需要 /data/flutter_assets,/data/icudtl.dat,/lib/libapp.so
        1.1.1 icudtl.dat 由FlutterTool提供,作为资源使用
        1.1.2 flutter_assets 由FlutterTool构建
        1.1.3 libapp.so 由FlutterTool构建,用于aot构建
    1.2 DartProject是官方的类,构造中仅保存三个文件路径

2. 创建flutter::FlutterViewController::ViewProperties对象,填充宽高,旋转角度,是否有光标等参数
3. 使用flutter::FlutterViewController::ViewProperties对象和flutter::DartProject对象构建FlutterWindow对象
    3.1 FlutterWindow对象应该就是自定义的

4. 调用FlutterWindow::OnCreate()方法启动引擎
    4.1 使用flutter::FlutterViewController::ViewProperties对象
        和flutter::DartProject对象构造flutter::FlutterViewController对象
        4.1.1 构造中会使用flutter::DartProject对象构造flutter::FlutterEngine对象
            4.1.1.1 构造中会从DartProject中取出argc,argv,以及三资源的路径初始化FlutterDesktopEngineProperties
            4.1.1.2 构造中会使用FlutterDesktopEngineProperties构造FlutterProjectBundle对象
            4.1.1.3 构造中会创建一个TaskRunner对象(用于执行任务), 运行时会检测engine是否为空,
                不为空则会调用flutter API接口运行task(engine为FlutterEngine(添加符号是为了以后拓展),此时还未初始化)
                  task_runner_ = std::make_unique<TaskRunner>( 
                          std::this_thread::get_id(), embedder_api_.GetCurrentTime,
                          [this](const auto* task) {      
                        if (!engine_) {
                              ELINUX_LOG(ERROR)
                                  << "Cannot post an engine task when engine is not running.";
                              return;
                        }
                        if (embedder_api_.RunTask(engine_, task) != kSuccess) {
                              ELINUX_LOG(ERROR) << "Failed to post an engine task.";
                        }
                      });
            4.1.1.3 构造中会使用FlutterProjectBundle对象构造FlutterELinuxEngine对象
                4.1.1.3.1 构造中初始化FlutterEngineProcTable对象(内含Flutter操作API)
                4.1.1.3.2 构造中构造FlutterDesktopMessenger对象,并使用FlutterELinuxEngine初始化engine成员
                4.1.1.3.3 构造中创建FlutterDesktopPluginRegistrar对象,并使用FlutterELinuxEngine初始化engine成员
                4.1.1.3.4 构造中使用FlutterDesktopMessenger对象构造BinaryMessengerImpl对象
                4.1.1.3.5 构造中使用FlutterDesktopMessenger对象构造IncomingMessageDispatcherImpl对象
                4.1.1.3.6 构造中使用FlutterELinuxEngine对象构造FlutterELinuxTextureRegistrar对象
                4.1.1.3.7 构造中使用FlutterDesktopMessager对象,JsonMessageCodec单例json解码器构建BasicMessageChannel对象
                    该消息通道的name为:"flutter/settings"
                4.1.1.3.8 构造中创建一个VsyncWaiter对象(通过该对象向flutter发送vsync事件)
            4.1.1.4 构造中会强制将FlutterELinuxEngine转化为FlutterDesktopEngine对象(实际就是个void*, 无法操作),
                并返回,目的是避免别人操作该对象,去掉类属性
            4.1.1.5 构造中会使用FlutterELinuxEngine对象中的FlutterDesktopMessenger对象构造BinaryMessengerImpl对象
        4.1.2 构造中会使用flutter::FlutterViewController::ViewProperties对象,
              构造FlutterDesktopViewProperties(flutter-elinux自定义)对象
        4.1.3 构造中会使用FlutterDesktopViewProperties对象
              和FlutterELinuxEngine对象调用FlutterDesktopViewControllerCreate
              构造flutter::FlutterDesktopViewController对象
            4.1.3.1 使用FlutterDesktopViewProperties构造ELinuxWindowX11(父类为WindowBindingHandler)对象
                4.1.3.1.1 构造函数中将会创建Display对象(XOpenDisplay()过去Display)
            4.1.3.2 构造FlutterDesktopViewControllerState对象
            4.1.3.3 使用ELinuxWindowX11(父类为WindowBindingHandler)对象构造
                    FlutterELinuxView(父类为WindowBindingHandlerDelegate)对象,
                并将FlutterELinuxView(父类为WindowBindingHandlerDelegate)对象保存到
                FlutterDesktopViewControllerState对象中。
                4.1.3.3.1 构造中还将FlutterELinuxView设置到ELinuxWindowX11中,实现双向绑定
            4.1.3.4 调用FlutterDesktopViewController对象的CreateRenderSurface方法
                4.1.3.4.1 获取ELinuxWindowX11的尺寸
                4.1.3.4.2 调用ELinuxWindowX11的CreateRenderSurface方法(以下属于X11窗口机制,需要花事件理解)
                    4.1.3.4.2.1 使用Display对象构造EnvromentEgl对象
                        4.1.3.4.2.1.1 构造中使用EGLNativeDisplayType(理论上Dispaly应该是EGLNativeDisplayType的父类)
                                  作为参数,调用eglGetDisplay获取EGLDisplay
                        4.1.3.4.2.1.2 调用InitializeEgl(初始化egl)
                    4.1.3.4.2.2 构造NativeWindowX11对象
                        4.1.3.4.2.2.1 创建EGLNativeWindowType对象(XCreateWindow)
                    4.1.3.4.2.3 使用EnvironmentElg对象构造SurfaceGL对象
                    4.1.3.4.2.4 将SurfaceGL对象和NativeWindowX11对象绑定
            4.1.3.5 调用FlutterELinuxView::SetEngine将FlutterElinuxEngine设置到FlutterELinuxView对象中(双向绑定)
                4.1.3.5.1 获取FlutterELinuxEngine中的FlutterDesktopPluginRegistrar对象
                      构造flutter::PluginRegistrar对象
                    4.1.3.5.1.1 使用FlutterDesktopPluginRegistrar中的FlutterDesktopMessenger
                            构造BinaryMessaengerImpl对象
                    4.1.3.5.1.2 获取FlutterDesktopPluginRegistrar中的FlutterELinuxTextureRegistrar对象,
                            并强制转换为FlutterDesktopTextureRegistrar(不可操作)
                    4.1.3.5.1.3 使用FlutterDesktopTextureRegistrar去构造TextureRegistrarImpl对象
                4.1.3.5.2 取出flutter::PluginRegistrar对象中的BinaryMessengerImpl对象
                4.1.3.5.3 使用BinaryMessengerImpl对象去构造flutter::KeyeventPlugin对象
                    4.1.3.5.3.1 构造中会初始化键盘输入上下文(xkb_context)
                4.1.3.5.4 使用ELinuxWindowX11(父类为WindowBindingHandler)对象和BinaryMessengerImpl对象
                      去构造flutter::TextInputPlugin对象
                    4.1.3.5.4.1 构造中会使用messenger和plugin去
                            构造flutter::MethodChannel<rapidjson::Document>对象
                    4.1.3.5.4.2 设置MethodChannel的回调,回调中收到事件后
                            传给ELinuxWindowX11(::UpdateVirtualKeyboardStatus)
                            (事件从哪里来)
                4.1.3.5.5 使用ELinuxWindowX11(父类为WindowBindingHandler)对象
                      和BinaryMessengerImpl对象去构造flutter::PlatformPlugin对象
                      (事件从哪里来)
                4.1.3.5.5 使用ELinuxWindowX11(父类为WindowBindingHandler)对象
                      和BinaryMessengerImpl对象去构造flutter::MouseCursorPlugin对象
                      (事件从哪里来)
                4.1.3.5.5 使用ELinuxWindowX11(父类为WindowBindingHandler)对象
                      和BinaryMessengerImpl对象去构造flutter::LifecyclePlugin对象
                      (事件从哪里来)
                4.1.3.5.5 使用ELinuxWindowX11(父类为WindowBindingHandler)对象
                      和BinaryMessengerImpl对象去构造flutter::NavigationPlugin对象
                      (事件从哪里来)
                4.1.3.5.5 使用ELinuxWindowX11(父类为WindowBindingHandler)对象
                      和BinaryMessengerImpl对象去构造flutter::PlatformViewsPlugin对象
                      (事件从哪里来)
            4.1.3.6 调用FlutterELinuxEngine::RunWithEntrypoint运行引擎
                4.1.3.6.1 调用FlutterProjectBundle::HasValidPaths检查路径是否有效
                4.1.3.6.2 调用flutter_api的RunsAOTCompilesDartCode,应该是编译dart代码
                4.1.3.6.3 调用FlutterProjectBundle::LoadAotData函数获取FlutterEngineAOTData对象
                    4.1.3.6.3.1 调用flutter_api的CreateAOTData构造FlutterEngineAOTData对象
                    (其内部将libapp.so映射出来,之后加载过程中解析libapp.so二进制文件的头,段表,以及记录.dynstr和.dynsym段位置,
                     然后读取段_kDartVmSnapshotData起始地址,保存到vm_data中
                     然后读取段_kDartVmSnapshotInstructions起始地址,保存到vm_instrs中
                     然后读取段_kDartIsolateSnapshotData起始地址,保存到isolate_data中
                     然后读取段_kDartIsolateSnapshotInstructions起始地址,保存到isolate_instrs中)
                4.1.3.6.4 调用GetSwitchesFromEnvironment获取环境变量FLUTTER_ENGINE_SWITCH_${N}
                      然后将环境变量值加上前缀转换为--observatory-port=12345的形势
                4.1.3.6.5 新建FlutterTaskRunnerDescription结构体对象
                      .struct_size = sizeof(FlutterTaskRunnerDescription)
                      .user_data = TaskRunner对象
                      // 判断是否是当前线程
                      .runs_task_on_current_thread_callback = [](void* user_data) -> bool {
                            return static_cast<TaskRunner*>(user_data)->RunsTasksOnCurrentThread();
                      };
                      // 抛出一个消息到主线程消息队列去执行
                      .post_task_callback = [](FlutterTask task,
                                   uint64_t target_time_nanos,
                                   void* user_data) -> void {
                        static_cast<TaskRunner*>(user_data)->PostFlutterTask(task, target_time_nanos);
                      }; 
                4.1.3.6.6 新建FlutterCustomTaskRunners结构体对象
                      .struct_size = sizeof(FlutterCustomTaskRunners)
                      .platform_task_runner = FlutterTaskRunnerDescription对象
                4.1.3.6.7 新建FlutterProjectArgs结构体对象
                      .struct_size = sizeof(FlutterCustomTaskRunners)
                      .assets_path = flutter_assets路径
                      .icu_data_path = icudtl.dat路径
                      // 引擎启动参数
                      .command_line_argc = 前面由环境变量生成的参数的个数
                      .command_line_argv = 前面由环境变量生成的参数
                      // dart脚本启动参数
                      .dart_entrypoint_arg = 前面由环境变量生成的参数的个数
                      .dart_entrypoint_argv = 前面由环境变量生成的参数
                      // 监听并处理flutter消息
                      .platform_message_callback = [](const FlutterPlatformMessage* engine_message,
                        void* user_data) -> void {
                            auto host = static_cast<FlutterELinuxEngine*>(user_data);
                            return host->HandlePlatformMessage(engine_message);
                      };
                      .custom_task_runners = FlutterCustomTaskRunners对象
                      .aot_data = FlutterEngineAOTData对象
                      // 指定dart脚本入口名, 为空默认main
                      .custom_dart_entrypoint = nullptr
                      // 日志消息处理
                      .log_message_callback = [](const char* tag, const char* message,void* user_data) {
                      };
                4.1.3.6.8 调用GetRendererConfig构造FlutterRenderConfig对象
                      // opengl引擎
                      config.type = kOpenGL
                      config.open_gl.struct_size = sizeof(config.open_gl)
                      config.open_gl.make_current = [](void* user_data) -> bool {
                        auto host = static_cast<FlutterELinuxEngine*>(user_data);
                        if (!host->view()) {
                            return false;
                        }
                        return host->view()->MakeCurrent();
                      };
                      config.open_gl.clear_current = [](void* user_data) -> bool {
                        auto host = static_cast<FlutterELinuxEngine*>(user_data);
                        if (!host->view()) {
                            return false;
                        }
                        return host->view()->ClearCurrent();
                      };
                      config.open_gl.present = [](void* user_data) -> bool {
                        auto host = static_cast<FlutterELinuxEngine*>(user_data);
                        if (!host->view()) {
                            return false;
                        }
                        return host->view()->Present();
                      }
                      config.open_gl.fbo_callback = [](void* user_data) -> uint32_t {
                        auto host = static_cast<FlutterELinuxEngine*>(user_data);
                        if (!host->view()) {
                            return false;
                        }
                        return host->view()->GetOnscreenFBO();
                      };
                      config.open_gl.gl_proc_resolver = [](void *user_data, 
                                        const char* name) -> void* {
                        auto host = static_cast<FlutterELinuxEngine*>(user_data);
                        if (!host->view()) {
                            return nullptr;
                        }
                        return host->view()->ProcResolver(name);
                      };
                      config.open_gl.make_resource_current = [](void* user_data) -> bool {
                        auto host = static_cast<FlutterELinuxEngine*>(user_data);
                        if (!host->view()) {
                            return false;
                        }
                        return host->view()->MakeResourceCurrent();
                      };
                      config.open_gl.gl_external_texture_frame_callback = [](void* user_data, 
                        int64_t texture_id, size_t width, size_t height, FlutterOpenGLTextture *texture) {
                        auto host = static_cast<FlutterELinuxEngine*>(user_data);
                        if (!host->texture_registrar()) {
                            return false;
                        }
                        return host->texture_registrar()->PopulateTexture(texture_id, width, height, texture);
                      };
                      config.open_gl.surface_transformation = [](void* user_data) {
                        auto host = static_cast<FlutterELinuxEngine*>(user_data);
                        return host->view()->GetRootSurfaceTransformation();
                      };
                4.1.3.6.9 调用flutter_api->Run(),将FlutterEngine对象和FlutterRenderConfig对象对象作为参数传入
                    4.1.3.6.9.1 FlutterEngine对象传入后,flutter引擎会调用FlutterEngine::messenger()接口获取消息传递对象BinaryMessengerImpl
                            (BinaryMessengerImpl内部持有FlutterDesktopMessenger,而FlutterDesktopMessenger内部持有FlutterELinuxEngine)
                    4.1.3.6.9.2 flutter获取BinaryMessengerImpl后,会调用SetMeesageHandler接口,传递通道名以及消息传递对象BinaryMessageHandler过来
                    4.1.3.6.9.3 然后会通过BinaryMessengerImpl深处的FlutterELinuxEngine对象的IncomingMessageDispatcher对象的SetMessageCallback接口
                    4.1.3.6.9.4 将handler转换成FlutterDesktopMessageCallback对象保存起来,当flutter消息过来时触发回调,并处理消息
                4.1.3.6.10 调用SendSystemSettings进行系统设置
                    4.1.3.6.9.1 获取所有支持的语言,并调用flutter_api的UpdateLocales,设置到引擎中
                    4.1.3.6.9.2 创建json的配置,调用BasicMessageChannel::Send发送配置
                    (发到flutter中,通道名为flutter/settings,
                    路线:BasicMessageChannel->BinaryMessengerImpl->FlutterDesktopMessengerSend->FlutterELinuxEngine::SendPlatformMessage)
    4.2 调用FlutterWindow::Run()进入引擎的事件传递,分发,及处理
        4.2.1 FlutterViewController对象->FlutterView::DispatchEvent()->FlutterELinuxView::DispatchEvent()->ELinuxWindowX11::DisplayEvent()
        4.2.2 ELinuxWindowX11::DispatchEvent中将调用XNextEvent()获取用户输入
        4.2.3 根据事件的不同类型调用FlutterELinuxView::OnKey()等等接口
            4.2.4.1 首先调用KeyeventPlugin::OnKey()接口
                4.2.4.1.1 通过构造KeyeventPlugin时初始化的BasicMessageChannel对象发送消息json格式的event事件
                4.2.4.1.2 通过构造KeyeventPlugin时传入的BinaryMessengerImpl对象(flutter::PluginRegistrar构造内创建)去发送消息
                4.2.4.1.3 调用FlutterDesktopMessengerSend接口去发送消息(第一个参数时FlutterELinuxEngine对象中的FlutterDeskTopMessenger对象)
                4.2.4.1.4 通过FlutterDeskTopMessenger对象中的FlutterELinuxEngine对象的SendPlatformMessageResponse接口去发送
                4.2.4.1.5 通过flutter_api->SendPlatformMessage去发送生成的PlatformMessage
        (VSync是由窗口wayland发起的,x11没有发起vsync)
 

(152)
打赏 支付红包 支付红包 微信打赏 微信打赏
上一篇 2023-09-07 19:14:10
下一篇 1970-01-01 08:00:00

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信