Recentemente, portamos com sucesso a estrutura Flutter para uma caixa de TV com uma plataforma de software RDK de código aberto. Neste artigo, discutiremos os desafios que enfrentamos e sugeriremos soluções para lançar e melhorar o desempenho com sucesso.
Dado que a pilha de software RDK ou Reference Design Kit agora Ă© ativamente usado para desenvolver aplicativos OTT, controle de voz para decodificadores e outros recursos avançados de vĂdeo sob demanda (VoD), querĂamos ver se o Flutter poderia ser executado em um set-top box. Descobriu-se que sim, mas, como costuma ser o caso, existem nuances.
A seguir, descreveremos o processo de portar e executar o Flutter em plataformas Linux embarcadas passo a passo e ver como este SDK de cĂłdigo aberto do Google se sente em hardware com recursos limitados e processadores ARM.
Flutter , -. « EFL + Wayland», node.js . , EFL — . node.js event-loop . Flutter .
, : SDK Google . Android. , iOS, Linux Google Fuchsia. :-) Flutter — Dart, JavaScript.
: Flutter - ? , Wayland + OpenGL. neon-? , , UI dart , Linux -.
Flutter Engine - ARM
, . Futter Wayland + OpenGL ES. Flutter Skia, OpenGL ES, .
Flutter ( - RDK), , . , .. - intel x86 . ARM-.
, Flutter Engine:
./flutter/tools/gn \
--embedder-for-target \
--target-os linux \
--linux-cpu arm \
--target-sysroot DEVICE_SYSROOT
--disable-desktop-embeddings \
--arm-float-abi hard
--target-toolchain /usr
--target-triple arm-linux-gnueabihf
--runtime-mode debug
ninja -C out/linux_debug_unopt_arm
: 32- ARM- Linux, --embedder-for-target
--disable-desktop-embeddings
.
clang 9 , .. Flutter, - gcc . — target-sysroot
RDK.
, , . flutter_engine.so .
flutter/dart /. :
flutter --local-engine-src-path PATH_TO_BUILDED_ENGINE_src
--local-engine=host_debug_unopt build bundle
! , , .. x86_64!
gn ninja x86_64! host_debug_unopt.
PATH_TO_BUILDED_ENGINE_src — , engine/src/out.
Flutter Engine embedder, Flutter Skia Dart-. Flutter linux-embedder, , , GTK-embedder, . , - GTK.
, (, , , github.com). GTK, , GTK-.
flutter-? , flutter_engine.so
FlutterEngineRun(FLUTTER_ENGINE_VERSION, &config, &args, display /* userdata */, &engine_);
( flutter bundle) FlutterProjectArgs args FlutterRendererConfig config.
bundle-, flutter-, OpenGL .
// github.com (flutter_application.cc)
, .
, . ? :-)
1.
, — . , egl- , FlutterRendererConfig , — . - . , eglBindAPI eglGetDisplay, nexus- ( BCM). Linux , .
:
egl_display_ = eglGetDisplay(display_);
if (egl_display_ == EGL_NO_DISPLAY) {
LogLastEGLError();
FL_ERROR("Could not access EGL display.");
return false;
}
if (eglInitialize(egl_display_, nullptr, nullptr) != EGL_TRUE) {
LogLastEGLError();
FL_ERROR("Could not initialize EGL display.");
return false;
}
if (eglBindAPI(EGL_OPENGL_ES_API) != EGL_TRUE) {
LogLastEGLError();
FL_ERROR("Could not bind the ES API.");
return false;
}
// github.com (wayland_display.cc) — , .. .
, , - :-).
2.
. , , (debug mode). - , - — , , - EFL+Node.js.
. SDK Flutter AOT, jit, , - Flutter. , .
// — github.com (elf.cc)
vm_snapshot_instructions_ = dlsym(fd, "_kDartVmSnapshotInstructions");
if (vm_snapshot_instructions_ == NULL) {
error_ = strerror(errno);
break;
}
vm_isolate_snapshot_instructions_ = dlsym(fd, "_kDartIsolateSnapshotInstructions");
if (vm_isolate_snapshot_instructions_ == NULL) {
error_ = strerror(errno);
break;
}
vm_snapshot_data_ = dlsym(fd, "_kDartVmSnapshotData");
if (vm_snapshot_data_ == NULL) {
error_ = strerror(errno);
break;
}
vm_isolate_snapshot_data_ = dlsym(fd, "_kDartIsolateSnapshotData");
if (vm_isolate_snapshot_data_ == NULL) {
error_ = strerror(errno);
break;
}
if (vm_snapshot_data_ == NULL ||
vm_snapshot_instructions_ == NULL ||
vm_isolate_snapshot_data_ == NULL ||
vm_isolate_snapshot_instructions_ == NULL) {
return false;
}
*vm_snapshot_data = reinterpret_cast <
const uint8_t * > (vm_snapshot_data_);
*vm_snapshot_instructions = reinterpret_cast <
const uint8_t * > (vm_snapshot_instructions_);
*vm_isolate_snapshot_data = reinterpret_cast <
const uint8_t * > (vm_isolate_snapshot_data_);
*vm_isolate_snapshot_instructions = reinterpret_cast <
const uint8_t * > (vm_isolate_snapshot_instructions_);
FlutterProjectArgs args;
// args
args.vm_snapshot_data = vm_snapshot_data;
args.vm_snapshot_instructions = vm_snapshot_instructions;
args.isolate_snapshot_data = vm_isolate_snapshot_data;
args.isolate_snapshot_instructions = vm_isolate_snapshot_instructions;
, , , AOT- . , dart-:
$HOST_ENGINE/dart-sdk/bin/dart \
--disable-dart-dev \
$HOST_ENGINE/gen/frontend_server.dart.snapshot \
--sdk-root $DEVICE_ENGINE}/flutter_patched_sdk/ \
--target=flutter \
-Ddart.developer.causal_async_stacks=false \
-Ddart.vm.profile=release \
-Ddart.vm.product=release \
--bytecode-options=source-positions \
--aot \
--tfa \
--packages .packages \
--output-dill build/tmp/app.dill \
--depfile build/kernel_snapshot.d \
package:lib/main.dart
$DEVICE_ENGINE/gen_snapshot \
--deterministic \
--snapshot_kind=app-aot-elf \
--elf=build/lib/libapp.so \
--no-causal-async-stacks \
--lazy-async-stacks \
build/tmp/app.dill
, . :
-Ddart.vm.profile=release \
-Ddart.vm.product=release \
, .
output-dill
libapp.so.
$DEVICE_ENGINE $HOST_ENGINE — (ARM) - (x86_64) . , libapp.so 32- ARM-:
$ file libapp.so
libapp.so: ELF 32-bit LSB shared object, ARM, EABI5 version 1 (SYSV),
dynamically linked
---... ! — !
! EFL. .
3.
4. - Linux Android 2—3
, UI-. UI , Linux Android. Flutter .
dart- . ( ). __brcm_cpu_dcache_flush khrn_copy_8888_to_tf32 ( Broadcom/BCM ). - . : :
//...
filter: new ImageFilter.blur(sigmaX: 10.0, sigmaY: 10.0),
//...
— 50-60 fps. , Flutter , - , .
, Flutter . RDK Wayland :
github.com/DEgITx/flutter_wayland
Esperamos que a experiĂŞncia de nossa equipe no desenvolvimento e portabilidade de software para decodificadores e Smart TVs seja Ăştil para vocĂŞ em seus projetos e sirva como ponto de partida para portar o Flutter para outros dispositivos.
[!?] Perguntas e comentários são bem-vindos. Elas serão respondidas pelo autor do artigo Alexey Kasyanchuk, nosso engenheiro de software