-
Notifications
You must be signed in to change notification settings - Fork 6k
Split AOT Android Embedder and shell #22179
Changes from all commits
a9776d6
ea56d3f
5b2cc97
2190ed4
5d64733
76071fb
396e40b
44e9750
32982a7
4df3e33
de074f8
feb4c99
49a0532
20d4e3e
b0002e4
340eb5e
cfeb109
ae7b771
9ed7094
eb3ccef
a1c603c
372adf9
e8861b5
4366c79
2130d59
b8cfc01
c995673
e4e9a1e
f006e9b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -260,6 +260,21 @@ class Engine final : public RuntimeDelegate, | |
| virtual std::unique_ptr<std::vector<std::string>> | ||
| ComputePlatformResolvedLocale( | ||
| const std::vector<std::string>& supported_locale_data) = 0; | ||
|
|
||
| //-------------------------------------------------------------------------- | ||
| /// @brief Invoked when the Dart VM requests that a deferred library | ||
| /// be loaded. Notifies the engine that the deferred library | ||
| /// identified by the specified loading unit id should be | ||
| /// downloaded and loaded into the Dart VM via | ||
| /// `LoadDartDeferredLibrary` | ||
| /// | ||
| /// @param[in] loading_unit_id The unique id of the deferred library's | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should clarify at this level what are we loading specifically? Is it the Dart specific loading units or is it the platform-specific bundles? We should be exact with the name. i.e. in the asset-only bundle case, that asset's still loaded through the Dart API or is it a different API?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I will be adding separate dart API for loading by android module name. This is currently strictly for the dart loadLibrary() code path. I'll link to additional info in a separate PR introducing the new API for module name/asset only loading. |
||
| /// loading unit. This id is to be passed | ||
| /// back into LoadDartDeferredLibrary | ||
| /// in order to identify which deferred | ||
| /// library to load. | ||
| /// | ||
| virtual void RequestDartDeferredLibrary(intptr_t loading_unit_id) = 0; | ||
| }; | ||
|
|
||
| //---------------------------------------------------------------------------- | ||
|
|
@@ -767,6 +782,38 @@ class Engine final : public RuntimeDelegate, | |
| /// | ||
| const std::string& InitialRoute() const { return initial_route_; } | ||
|
|
||
| //-------------------------------------------------------------------------- | ||
| /// @brief Loads the Dart shared library into the Dart VM. When the | ||
| /// Dart library is loaded successfully, the Dart future | ||
| /// returned by the originating loadLibrary() call completes. | ||
| /// | ||
| /// The Dart compiler may generate separate shared libraries | ||
| /// files called 'loading units' when libraries are imported | ||
| /// as deferred. Each of these shared libraries are identified | ||
| /// by a unique loading unit id. Callers should dlopen the | ||
| /// shared library file and use dlsym to resolve the dart | ||
| /// symbols. These symbols can then be passed to this method to | ||
| /// be dynamically loaded into the VM. | ||
| /// | ||
| /// This method is paired with a RequestDartDeferredLibrary | ||
| /// invocation that provides the embedder with the loading unit id | ||
| /// of the deferred library to load. | ||
| /// | ||
| /// | ||
| /// @param[in] loading_unit_id The unique id of the deferred library's | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Explicitly state this loading unit id's relationship with the previous request call? Or are they independent?
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You didn't address this one. The 2 functions' docs should explicitly cross-reference each other. |
||
| /// loading unit, as passed in by | ||
| /// RequestDartDeferredLibrary. | ||
| /// | ||
| /// @param[in] snapshot_data Dart snapshot data of the loading unit's | ||
| /// shared library. | ||
| /// | ||
| /// @param[in] snapshot_data Dart snapshot instructions of the loading | ||
| /// unit's shared library. | ||
| /// | ||
| void LoadDartDeferredLibrary(intptr_t loading_unit_id, | ||
| const uint8_t* snapshot_data, | ||
| const uint8_t* snapshot_instructions); | ||
|
|
||
| private: | ||
| Engine::Delegate& delegate_; | ||
| const Settings settings_; | ||
|
|
@@ -815,6 +862,12 @@ class Engine final : public RuntimeDelegate, | |
| std::unique_ptr<std::vector<std::string>> ComputePlatformResolvedLocale( | ||
| const std::vector<std::string>& supported_locale_data) override; | ||
|
|
||
| // The Following commented out code connects into part 2 of the split AOT | ||
| // feature. Left commented out until it lands: | ||
|
|
||
| // // |RuntimeDelegate| | ||
| // void RequestDartDeferredLibrary(intptr_t loading_unit_id) override; | ||
|
|
||
| void SetNeedsReportTimings(bool value) override; | ||
|
|
||
| void StopAnimator(); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -210,6 +210,43 @@ class PlatformView { | |
| /// | ||
| virtual void OnPlatformViewMarkTextureFrameAvailable( | ||
| int64_t texture_id) = 0; | ||
|
|
||
| //-------------------------------------------------------------------------- | ||
| /// @brief Loads the dart shared library into the dart VM. When the | ||
GaryQian marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| /// dart library is loaded successfully, the dart future | ||
| /// returned by the originating loadLibrary() call completes. | ||
| /// | ||
| /// The Dart compiler may generate separate shared library .so | ||
| /// files called 'loading units' when libraries are imported | ||
| /// as deferred. Each of these shared libraries are identified | ||
| /// by a unique loading unit id and can be dynamically loaded | ||
| /// into the VM by dlopen-ing and resolving the data and | ||
| /// instructions symbols. | ||
| /// | ||
| /// | ||
| /// @param[in] loading_unit_id The unique id of the deferred library's | ||
| /// loading unit. | ||
| /// | ||
| /// @param[in] snapshot_data Dart snapshot data of the loading unit's | ||
| /// shared library. | ||
| /// | ||
| /// @param[in] snapshot_data Dart snapshot instructions of the loading | ||
| /// unit's shared library. | ||
| /// | ||
| virtual void LoadDartDeferredLibrary( | ||
| intptr_t loading_unit_id, | ||
| const uint8_t* snapshot_data, | ||
| const uint8_t* snapshot_instructions) = 0; | ||
|
|
||
| // TODO(garyq): Implement a proper asset_resolver replacement instead of | ||
| // overwriting the entire asset manager. | ||
| //-------------------------------------------------------------------------- | ||
| /// @brief Sets the asset manager of the engine to asset_manager | ||
| /// | ||
| /// @param[in] asset_manager The asset manager to use. | ||
| /// | ||
| virtual void UpdateAssetManager( | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. noob question / I might not really understand how this works: how come it's implemented as replacing the asset manager instead of pushing a new resolver inside the existing manager?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I mentioned this in a TODO somewhere, This "replacement" is temporary. I plan on implementing a system to push a new asset resolver, but the challenge is to track and dispose of the previous APKAssetResolver to prevent a leak. For now, this is more of a stand-in implementation. I expect the full implementation to require additional research and/or new features in the asset manager to be able to specifically find and replace a particular asset resolver. I'd like to do it in a separate PR.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ah ok, leave a TODO so future maintainers don't pile onto this
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You didn't address this one yet.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There is a TODO in one of the other versions of this, I'll add it here too. |
||
| std::shared_ptr<AssetManager> asset_manager) = 0; | ||
| }; | ||
|
|
||
| //---------------------------------------------------------------------------- | ||
|
|
@@ -565,6 +602,62 @@ class PlatformView { | |
|
|
||
| virtual std::shared_ptr<ExternalViewEmbedder> CreateExternalViewEmbedder(); | ||
|
|
||
| //-------------------------------------------------------------------------- | ||
| /// @brief Invoked when the dart VM requests that a deferred library | ||
| /// be loaded. Notifies the engine that the deferred library | ||
| /// identified by the specified loading unit id should be | ||
| /// downloaded and loaded into the Dart VM via | ||
| /// `LoadDartDeferredLibrary` | ||
| /// | ||
| /// @param[in] loading_unit_id The unique id of the deferred library's | ||
| /// loading unit. This id is to be passed | ||
| /// back into LoadDartDeferredLibrary | ||
| /// in order to identify which deferred | ||
| /// library to load. | ||
| /// | ||
| virtual void RequestDartDeferredLibrary(intptr_t loading_unit_id); | ||
|
|
||
| //-------------------------------------------------------------------------- | ||
| /// @brief Loads the Dart shared library into the Dart VM. When the | ||
| /// Dart library is loaded successfully, the Dart future | ||
| /// returned by the originating loadLibrary() call completes. | ||
| /// | ||
| /// The Dart compiler may generate separate shared libraries | ||
| /// files called 'loading units' when libraries are imported | ||
| /// as deferred. Each of these shared libraries are identified | ||
| /// by a unique loading unit id. Callers should dlopen the | ||
| /// shared library file and use dlsym to resolve the dart | ||
| /// symbols. These symbols can then be passed to this method to | ||
| /// be dynamically loaded into the VM. | ||
| /// | ||
| /// This method is paired with a RequestDartDeferredLibrary | ||
| /// invocation that provides the embedder with the loading unit id | ||
| /// of the deferred library to load. | ||
| /// | ||
| /// | ||
| /// @param[in] loading_unit_id The unique id of the deferred library's | ||
| /// loading unit, as passed in by | ||
| /// RequestDartDeferredLibrary. | ||
| /// | ||
| /// @param[in] snapshot_data Dart snapshot data of the loading unit's | ||
| /// shared library. | ||
| /// | ||
| /// @param[in] snapshot_data Dart snapshot instructions of the loading | ||
| /// unit's shared library. | ||
| /// | ||
| virtual void LoadDartDeferredLibrary(intptr_t loading_unit_id, | ||
| const uint8_t* snapshot_data, | ||
| const uint8_t* snapshot_instructions); | ||
|
|
||
| // TODO(garyq): Implement a proper asset_resolver replacement instead of | ||
| // overwriting the entire asset manager. | ||
| //-------------------------------------------------------------------------- | ||
| /// @brief Sets the asset manager of the engine to asset_manager | ||
| /// | ||
| /// @param[in] asset_manager The asset manager to use. | ||
| /// | ||
| virtual void UpdateAssetManager(std::shared_ptr<AssetManager> asset_manager); | ||
|
|
||
| protected: | ||
| PlatformView::Delegate& delegate_; | ||
| const TaskRunners task_runners_; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1185,6 +1185,22 @@ std::unique_ptr<std::vector<std::string>> Shell::ComputePlatformResolvedLocale( | |
| return platform_view_->ComputePlatformResolvedLocales(supported_locale_data); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. is this related?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh this is not related. I realized that one of the calls was extraneous and decided to fix it. I'll move this to a separate PR.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Separate PR here: #22362 |
||
| } | ||
|
|
||
| void Shell::LoadDartDeferredLibrary(intptr_t loading_unit_id, | ||
| const uint8_t* snapshot_data, | ||
| const uint8_t* snapshot_instructions) { | ||
| engine_->LoadDartDeferredLibrary(loading_unit_id, snapshot_data, | ||
| snapshot_instructions); | ||
| } | ||
|
|
||
| void Shell::UpdateAssetManager(std::shared_ptr<AssetManager> asset_manager) { | ||
| engine_->UpdateAssetManager(std::move(asset_manager)); | ||
GaryQian marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| // |Engine::Delegate| | ||
| void Shell::RequestDartDeferredLibrary(intptr_t loading_unit_id) { | ||
| platform_view_->RequestDartDeferredLibrary(loading_unit_id); | ||
| } | ||
|
|
||
| void Shell::ReportTimings() { | ||
| FML_DCHECK(is_setup_); | ||
| FML_DCHECK(task_runners_.GetRasterTaskRunner()->RunsTasksOnCurrentThread()); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -48,6 +48,12 @@ android { | |
| embedding "androidx.lifecycle:lifecycle-common:$lifecycle_version" | ||
| embedding "androidx.lifecycle:lifecycle-common-java8:$lifecycle_version" | ||
|
|
||
| // This dependency is here to allow linking to Play core in tests, but | ||
| // is not used in a default Flutter app. This dependency should be manually | ||
| // added to the user's app gradle in order to opt into using split AOT | ||
| // dynamic features. | ||
| embedding "com.google.android.play:core:1.8.0" | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 28k seems borderline ok. I'd still like us to break down exactly what those 28k are. Are they all dex? If so, what's the package/class breakdown. Are we using all of them? Are there proguard rules we should tweak after adding this.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This PR no longer imports the Play core dependent classes, leaving them as floating classes for now, which can be opted into by the developer when deciding to use this feature.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add a comment here to say that it's just here for test but not really added to the engine's dependencies? |
||
|
|
||
| // Testing | ||
| // TODO(xster): remove these android-all compile time dependencies. | ||
| // Use https://github.com/robolectric/robolectric/blob/master/robolectric/src/main/java/org/robolectric/plugins/LegacyDependencyResolver.java#L24 | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is all fine for a local build but you still need to update
engine/shell/platform/android/BUILD.gn
Line 394 in 6166712
i.e. I don't think this will compile on LUCI. @jason-simmons might know more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The LUCI tests were able to all pass on this PR this afternoon, I'll take a look at updating it in the above mentioned spot too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it'll pass on LUCI since the tests will run in the "development path". But I think it won't package up the dependencies in the vendored engine build on cloud storage.