How to port the Flutter SDK to a TV box to develop and run Android TV apps

We have recently successfully ported the Flutter framework to a TV box with an open source RDK software platform. In this article, we will discuss the challenges we faced and suggest solutions to successfully launch and improve performance. 





Given that the RDK software stack or Reference Design Kit is now actively used to develop OTT applications, voice control for set-top boxes, and other advanced video-on-demand (VoD) features, we wanted to see if Flutter could run on a set-top box. It turned out that yes, but, as is usually the case, there are nuances.





Next, we will outline the process of porting and running Flutter on embedded Linux platforms step by step and see how this open source SDK from Google feels on hardware with limited resources and ARM processors.





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. , .





, FlutterEngineRun





// β€” 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.





, Wayland , .





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





We hope that the experience of our team in developing and porting software for set-top boxes and Smart TVs will be useful to you in your projects and will serve as a starting point for porting Flutter to other devices.





[!?] Questions and comments are welcome. They will be answered by the author of the article Alexey Kasyanchuk, our software engineer








All Articles