Skip to content
This repository has been archived by the owner on Feb 14, 2025. It is now read-only.

Hacks for iOS demo #19

Merged
merged 1 commit into from
Jun 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions DEPS
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,10 @@ vars = {
'ocmock_git': 'https://github.com/erikdoe/ocmock.git',
'skia_revision': 'ad8fa4a38668a9671d5aa24faa92cb4f53cf15f1',

'dart_sdk_revision': '96ac26bd7342b38251866bb669128f432fb14fda',
'dart_sdk_git': 'https://github.com/shorebirdtech/dart-sdk.git',
'updater_git': 'https://github.com/shorebirdtech/updater.git',
'updater_rev': '11d8c2280539f08d55c5bd0b019adbd5cfa373dc',
'updater_rev': '4d2ec2e148f5205cf018f0eb854113d9d8b380b3',

# WARNING: DO NOT EDIT canvaskit_cipd_instance MANUALLY
# See `lib/web_ui/README.md` for how to roll CanvasKit to a new version.
Expand Down Expand Up @@ -325,7 +327,7 @@ deps = {
Var('fuchsia_git') + '/protobuf-gn' + '@' + Var('dart_protobuf_gn_rev'),

'src/third_party/dart':
Var('dart_git') + '/sdk.git' + '@' + Var('dart_revision'),
Var('dart_sdk_git') + '@' + Var('dart_sdk_revision'),

# WARNING: Unused Dart dependencies in the list below till "WARNING:" marker are removed automatically - see create_updated_flutter_deps.py.

Expand Down
40 changes: 40 additions & 0 deletions runtime/dart_snapshot.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#include <sstream>

#include <third_party/dart/runtime/bin/elf_loader.h>
#include "flutter/fml/native_library.h"
#include "flutter/fml/paths.h"
#include "flutter/fml/trace_event.h"
Expand Down Expand Up @@ -56,6 +57,45 @@ static std::shared_ptr<const fml::Mapping> SearchMapping(
const std::vector<std::string>& native_library_path,
const char* native_library_symbol_name,
bool is_executable) {
// Quick hack to make this only included in device builds.
#if FML_OS_IOS
static Dart_LoadedElf* leaked_elf = nullptr;
static const uint8_t* vm_snapshot_data = nullptr;
static const uint8_t* vm_snapshot_instrs = nullptr;
static const uint8_t* vm_isolate_data = nullptr;
static const uint8_t* vm_isolate_instrs = nullptr;
if (leaked_elf == nullptr) {
const char* error = nullptr;
leaked_elf = Dart_LoadELF(native_library_path.back().c_str(), 0, &error,
&vm_snapshot_data, &vm_snapshot_instrs,
&vm_isolate_data, &vm_isolate_instrs);
if (leaked_elf != nullptr) {
FML_LOG(INFO) << "Loaded ELF";
} else {
FML_LOG(FATAL) << "Failed to load ELF" << error;
abort();
}
}

FML_LOG(INFO) << "Loading symbol from ELF " << native_library_symbol_name;

if (native_library_symbol_name == DartSnapshot::kVMDataSymbol) {
return std::make_unique<const fml::NonOwnedMapping>(vm_snapshot_data, 0,
nullptr, true);
} else if (native_library_symbol_name ==
DartSnapshot::kVMInstructionsSymbol) {
return std::make_unique<const fml::NonOwnedMapping>(vm_snapshot_instrs, 0,
nullptr, true);
} else if (native_library_symbol_name == DartSnapshot::kIsolateDataSymbol) {
return std::make_unique<const fml::NonOwnedMapping>(vm_isolate_data, 0,
nullptr, true);
} else if (native_library_symbol_name ==
DartSnapshot::kIsolateInstructionsSymbol) {
return std::make_unique<const fml::NonOwnedMapping>(vm_isolate_instrs, 0,
nullptr, true);
}
#endif

// Ask the embedder. There is no fallback as we expect the embedders (via
// their embedding APIs) to just specify the mappings directly.
if (embedder_mapping_callback) {
Expand Down
103 changes: 103 additions & 0 deletions shell/common/shorebird.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@

#include "flutter/shell/common/shorebird.h"

#include <optional>
#include <vector>

#include "flutter/fml/command_line.h"
#include "flutter/fml/file.h"
#include "flutter/fml/macros.h"
#include "flutter/fml/message_loop.h"
#include "flutter/fml/native_library.h"
#include "flutter/fml/paths.h"
#include "flutter/fml/size.h"
#include "flutter/lib/ui/plugins/callback_cache.h"
#include "flutter/runtime/dart_vm.h"
#include "flutter/shell/common/shell.h"
#include "flutter/shell/common/switches.h"
#include "third_party/dart/runtime/include/dart_tools_api.h"
#include "third_party/skia/include/core/SkFontMgr.h"

#include "third_party/updater/library/include/updater.h"

// Namespaced to avoid Google style warnings.
namespace flutter {

// Old Android versions (e.g. the v16 ndk Flutter uses) don't always include a
// getauxval symbol, but the Rust ring crate assumes it exists:
// https://github.com/briansmith/ring/blob/fa25bf3a7403c9fe6458cb87bd8427be41225ca2/src/cpu/arm.rs#L22
// It uses it to determine if the CPU supports AES instructions.
// Making this a weak symbol allows the linker to use a real version instead
// if it can find one.
// BoringSSL just reads from procfs instead, which is what we would do if
// we needed to implement this ourselves. Implementation looks straightforward:
// https://lwn.net/Articles/519085/
// https://github.com/google/boringssl/blob/6ab4f0ae7f2db96d240eb61a5a8b4724e5a09b2f/crypto/cpu_arm_linux.c
#if defined(__ANDROID__) && defined(__arm__)
extern "C" __attribute__((weak)) unsigned long getauxval(unsigned long type) {
return 0;
}
#endif

void ConfigureShorebird(std::string cache_path,
flutter::Settings& settings,
const std::string& shorebird_yaml,
const std::string& version,
int64_t version_code) {
auto cache_dir =
fml::paths::JoinPaths({std::move(cache_path), "shorebird_updater"});

fml::CreateDirectory(fml::paths::GetCachesDirectory(), {"shorebird_updater"},
fml::FilePermission::kReadWrite);

// Using a block to make AppParameters lifetime explicit.
{
AppParameters app_parameters;
// Combine version and version_code into a single string.
// We could also pass these separately through to the updater if needed.
auto release_version = version + "+" + std::to_string(version_code);
app_parameters.release_version = release_version.c_str();
app_parameters.cache_dir = cache_dir.c_str();

// https://stackoverflow.com/questions/26032039/convert-vectorstring-into-char-c
std::vector<const char*> c_paths{};
for (const auto& string : settings.application_library_path) {
c_paths.push_back(string.c_str());
}
// Do not modify application_library_path or c_strings will invalidate.

app_parameters.original_libapp_paths = c_paths.data();
app_parameters.original_libapp_paths_size = c_paths.size();

// shorebird_init copies from app_parameters and shorebirdYaml.
shorebird_init(&app_parameters, shorebird_yaml.c_str());
}

char* c_active_path = shorebird_next_boot_patch_path();
if (c_active_path != NULL) {
std::string active_path = c_active_path;
shorebird_free_string(c_active_path);
FML_LOG(INFO) << "Shorebird updater: active path: " << active_path;
char* c_patch_number = shorebird_next_boot_patch_number();
if (c_patch_number != NULL) {
std::string patch_number = c_patch_number;
shorebird_free_string(c_patch_number);
FML_LOG(INFO) << "Shorebird updater: active patch number: "
<< patch_number;
}

settings.application_library_path.clear();
settings.application_library_path.emplace_back(active_path);
// Once start_update_thread is called, the next_boot_patch* functions may
// change their return values if the shorebird_report_launch_failed
// function is called.
shorebird_report_launch_start();
} else {
FML_LOG(INFO) << "Shorebird updater: no active patch.";
}

FML_LOG(INFO) << "Starting Shorebird update";
shorebird_start_update_thread();
}

} // namespace flutter
16 changes: 16 additions & 0 deletions shell/common/shorebird.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#ifndef SHELL_COMMON_SHOREBIRD_H_
#define SHELL_COMMON_SHOREBIRD_H_

#include "flutter/common/settings.h"

namespace flutter {

void ConfigureShorebird(std::string cache_path,
flutter::Settings& settings,
const std::string& shorebird_yaml,
const std::string& version,
int64_t version_code);

} // namespace flutter

#endif // SHELL_COMMON_SHOREBIRD_H_
2 changes: 2 additions & 0 deletions shell/platform/android/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ source_set("flutter_shell_native_src") {

sources = [
"$root_build_dir/flutter_icu/icudtl.o",
"../../common/shorebird.cc",
"../../common/shorebird.h",
"android_choreographer.cc",
"android_choreographer.h",
"android_context_gl_impeller.cc",
Expand Down
79 changes: 1 addition & 78 deletions shell/platform/android/flutter_main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "flutter/lib/ui/plugins/callback_cache.h"
#include "flutter/runtime/dart_vm.h"
#include "flutter/shell/common/shell.h"
#include "flutter/shell/common/shorebird.h"
#include "flutter/shell/common/switches.h"
#include "third_party/dart/runtime/include/dart_tools_api.h"
#include "third_party/skia/include/core/SkFontMgr.h"
Expand Down Expand Up @@ -77,84 +78,6 @@ const flutter::Settings& FlutterMain::GetSettings() const {
return settings_;
}

// Old Android versions (e.g. the v16 ndk Flutter uses) don't always include a
// getauxval symbol, but the Rust ring crate assumes it exists:
// https://github.com/briansmith/ring/blob/fa25bf3a7403c9fe6458cb87bd8427be41225ca2/src/cpu/arm.rs#L22
// It uses it to determine if the CPU supports AES instructions.
// Making this a weak symbol allows the linker to use a real version instead
// if it can find one.
// BoringSSL just reads from procfs instead, which is what we would do if
// we needed to implement this ourselves. Implementation looks straightforward:
// https://lwn.net/Articles/519085/
// https://github.com/google/boringssl/blob/6ab4f0ae7f2db96d240eb61a5a8b4724e5a09b2f/crypto/cpu_arm_linux.c
#if defined(__ANDROID__) && defined(__arm__)
extern "C" __attribute__((weak)) unsigned long getauxval(unsigned long type) {
return 0;
}
#endif

// TODO: Move this out into a separate file?
void ConfigureShorebird(std::string android_cache_path,
flutter::Settings& settings,
std::string shorebirdYaml,
std::string version,
long version_code) {
auto cache_dir =
fml::paths::JoinPaths({android_cache_path, "shorebird_updater"});

fml::CreateDirectory(fml::paths::GetCachesDirectory(), {"shorebird_updater"},
fml::FilePermission::kReadWrite);

// Using a block to make AppParameters lifetime explicit.
{
AppParameters app_parameters;
// Combine version and version_code into a single string.
// We could also pass these separately through to the updater if needed.
auto release_version = version + "+" + std::to_string(version_code);
app_parameters.release_version = release_version.c_str();
app_parameters.cache_dir = cache_dir.c_str();

// https://stackoverflow.com/questions/26032039/convert-vectorstring-into-char-c
std::vector<const char*> c_paths{};
for (const auto& string : settings.application_library_path) {
c_paths.push_back(string.c_str());
}
// Do not modify application_library_path or c_strings will invalidate.

app_parameters.original_libapp_paths = c_paths.data();
app_parameters.original_libapp_paths_size = c_paths.size();

// shorebird_init copies from app_parameters and shorebirdYaml.
shorebird_init(&app_parameters, shorebirdYaml.c_str());
}

char* c_active_path = shorebird_next_boot_patch_path();
if (c_active_path != NULL) {
std::string active_path = c_active_path;
shorebird_free_string(c_active_path);
FML_LOG(INFO) << "Shorebird updater: active path: " << active_path;
char* c_patch_number = shorebird_next_boot_patch_number();
if (c_patch_number != NULL) {
std::string patch_number = c_patch_number;
shorebird_free_string(c_patch_number);
FML_LOG(INFO) << "Shorebird updater: active patch number: "
<< patch_number;
}

settings.application_library_path.clear();
settings.application_library_path.emplace_back(active_path);
// Once start_update_thread is called, the next_boot_patch* functions may
// change their return values if the shorebird_report_launch_failed
// function is called.
shorebird_report_launch_start();
} else {
FML_LOG(INFO) << "Shorebird updater: no active patch.";
}

FML_LOG(INFO) << "Starting Shorebird update";
shorebird_start_update_thread();
}

void FlutterMain::Init(JNIEnv* env,
jclass clazz,
jobject context,
Expand Down
13 changes: 13 additions & 0 deletions shell/platform/darwin/ios/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ source_set("flutter_framework_source") {
deps = []

sources = [
"../../../common/shorebird.cc",
"../../../common/shorebird.h",
"framework/Source/FlutterAppDelegate.mm",
"framework/Source/FlutterBinaryMessengerRelay.mm",
"framework/Source/FlutterCallbackCache.mm",
Expand Down Expand Up @@ -187,6 +189,7 @@ source_set("flutter_framework_source") {
"//flutter/shell/platform/embedder:embedder_as_internal_library",
"//flutter/shell/profiling:profiling",
"//flutter/third_party/spring_animation",
"//third_party/dart/runtime/bin:elf_loader",
"//third_party/skia",
]

Expand All @@ -195,6 +198,16 @@ source_set("flutter_framework_source") {
"//flutter:config",
]

if (target_cpu == "arm64") {
libs =
[ "//third_party/updater/target/aarch64-apple-ios/debug/libupdater.a" ]
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should have been release.

} else if (target_cpu == "x64") {
libs =
[ "//third_party/updater/target/x86_64-apple-ios/debug/libupdater.a" ]
} else {
assert(false, "Unsupported target_cpu")
}

frameworks = [
"AudioToolbox.framework",
"CoreMedia.framework",
Expand Down
Loading