diff --git a/DEPS b/DEPS index 989eaca615a54..067552383237c 100644 --- a/DEPS +++ b/DEPS @@ -482,7 +482,7 @@ deps = { 'packages': [ { 'package': 'flutter/android/embedding_bundle', - 'version': 'last_updated:2020-09-11T17:57:41-0700' + 'version': 'last_updated:2020-05-20T01:36:16-0700' } ], 'condition': 'download_android_deps', diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index d7eb1dac4dc2a..b2a91424b1af5 100755 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -747,8 +747,6 @@ FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/Flutte FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/dart/DartExecutor.java FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/dart/DartMessenger.java FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/dart/PlatformMessageHandler.java -FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/dynamicfeatures/DynamicFeatureManager.java -FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/dynamicfeatures/PlayStoreDynamicFeatureManager.java FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/loader/ApplicationInfoLoader.java FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/loader/FlutterApplicationInfo.java FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/loader/FlutterLoader.java diff --git a/shell/common/engine.cc b/shell/common/engine.cc index 1b9c02413138b..6c9304f1ad945 100644 --- a/shell/common/engine.cc +++ b/shell/common/engine.cc @@ -507,21 +507,4 @@ const std::string& Engine::GetLastEntrypointLibrary() const { return last_entry_point_library_; } -// The Following commented out code connects into part 2 of the split AOT -// feature. Left commented out until it lands: - -// // |RuntimeDelegate| -// void Engine::RequestDartDeferredLibrary(intptr_t loading_unit_id) { -// return delegate_.RequestDartDeferredLibrary(loading_unit_id); -// } - -void Engine::LoadDartDeferredLibrary(intptr_t loading_unit_id, - const uint8_t* snapshot_data, - const uint8_t* snapshot_instructions) { - if (runtime_controller_->IsRootIsolateRunning()) { - // runtime_controller_->LoadDartDeferredLibrary(loading_unit_id, - // snapshot_data, snapshot_instructions); - } -} - } // namespace flutter diff --git a/shell/common/engine.h b/shell/common/engine.h index 93a5f2367dbc3..1eb2cf36ecc72 100644 --- a/shell/common/engine.h +++ b/shell/common/engine.h @@ -260,21 +260,6 @@ class Engine final : public RuntimeDelegate, virtual std::unique_ptr> ComputePlatformResolvedLocale( const std::vector& 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 - /// 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; }; //---------------------------------------------------------------------------- @@ -782,38 +767,6 @@ 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 - /// 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_; @@ -862,12 +815,6 @@ class Engine final : public RuntimeDelegate, std::unique_ptr> ComputePlatformResolvedLocale( const std::vector& 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(); diff --git a/shell/common/engine_unittests.cc b/shell/common/engine_unittests.cc index e563a92a454a4..7405511513a9b 100644 --- a/shell/common/engine_unittests.cc +++ b/shell/common/engine_unittests.cc @@ -32,7 +32,6 @@ class MockDelegate : public Engine::Delegate { MOCK_METHOD1(ComputePlatformResolvedLocale, std::unique_ptr>( const std::vector&)); - MOCK_METHOD1(RequestDartDeferredLibrary, void(intptr_t)); }; class MockResponse : public PlatformMessageResponse { @@ -56,7 +55,6 @@ class MockRuntimeDelegate : public RuntimeDelegate { MOCK_METHOD1(ComputePlatformResolvedLocale, std::unique_ptr>( const std::vector&)); - MOCK_METHOD1(RequestDartDeferredLibrary, void(intptr_t)); }; class MockRuntimeController : public RuntimeController { diff --git a/shell/common/platform_view.cc b/shell/common/platform_view.cc index 55d3ebbcc7147..3e2b1daa476a6 100644 --- a/shell/common/platform_view.cc +++ b/shell/common/platform_view.cc @@ -159,14 +159,4 @@ PlatformView::ComputePlatformResolvedLocales( return out; } -void PlatformView::RequestDartDeferredLibrary(intptr_t loading_unit_id) {} - -void PlatformView::LoadDartDeferredLibrary( - intptr_t loading_unit_id, - const uint8_t* snapshot_data, - const uint8_t* snapshot_instructions) {} - -void PlatformView::UpdateAssetManager( - std::shared_ptr asset_manager) {} - } // namespace flutter diff --git a/shell/common/platform_view.h b/shell/common/platform_view.h index dd200b5948fdb..07ba3a1bb6d93 100644 --- a/shell/common/platform_view.h +++ b/shell/common/platform_view.h @@ -210,43 +210,6 @@ class PlatformView { /// virtual void OnPlatformViewMarkTextureFrameAvailable( int64_t texture_id) = 0; - - //-------------------------------------------------------------------------- - /// @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 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( - std::shared_ptr asset_manager) = 0; }; //---------------------------------------------------------------------------- @@ -602,62 +565,6 @@ class PlatformView { virtual std::shared_ptr 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 asset_manager); - protected: PlatformView::Delegate& delegate_; const TaskRunners task_runners_; diff --git a/shell/common/shell.cc b/shell/common/shell.cc index aaf3c3c2242ae..a8a8b884e4c0f 100644 --- a/shell/common/shell.cc +++ b/shell/common/shell.cc @@ -1185,22 +1185,6 @@ std::unique_ptr> Shell::ComputePlatformResolvedLocale( return platform_view_->ComputePlatformResolvedLocales(supported_locale_data); } -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 asset_manager) { - engine_->UpdateAssetManager(std::move(asset_manager)); -} - -// |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()); diff --git a/shell/common/shell.h b/shell/common/shell.h index 7ac297e5d07c6..ffb07b877d493 100644 --- a/shell/common/shell.h +++ b/shell/common/shell.h @@ -507,14 +507,6 @@ class Shell final : public PlatformView::Delegate, // |PlatformView::Delegate| void OnPlatformViewSetNextFrameCallback(const fml::closure& closure) override; - // |PlatformView::Delegate| - void LoadDartDeferredLibrary(intptr_t loading_unit_id, - const uint8_t* snapshot_data, - const uint8_t* snapshot_instructions) override; - - // |PlatformView::Delegate| - void UpdateAssetManager(std::shared_ptr asset_manager) override; - // |Animator::Delegate| void OnAnimatorBeginFrame(fml::TimePoint frame_target_time) override; @@ -556,9 +548,6 @@ class Shell final : public PlatformView::Delegate, std::unique_ptr> ComputePlatformResolvedLocale( const std::vector& supported_locale_data) override; - // |Engine::Delegate| - void RequestDartDeferredLibrary(intptr_t loading_unit_id) override; - // |Rasterizer::Delegate| void OnFrameRasterized(const FrameTiming&) override; diff --git a/shell/platform/android/BUILD.gn b/shell/platform/android/BUILD.gn index 29f204fd82dcc..a7ebd146db06e 100644 --- a/shell/platform/android/BUILD.gn +++ b/shell/platform/android/BUILD.gn @@ -156,8 +156,6 @@ android_java_sources = [ "io/flutter/embedding/engine/dart/DartExecutor.java", "io/flutter/embedding/engine/dart/DartMessenger.java", "io/flutter/embedding/engine/dart/PlatformMessageHandler.java", - "io/flutter/embedding/engine/dynamicfeatures/DynamicFeatureManager.java", - "io/flutter/embedding/engine/dynamicfeatures/PlayStoreDynamicFeatureManager.java", "io/flutter/embedding/engine/loader/ApplicationInfoLoader.java", "io/flutter/embedding/engine/loader/FlutterApplicationInfo.java", "io/flutter/embedding/engine/loader/FlutterLoader.java", @@ -464,7 +462,6 @@ action("robolectric_tests") { "test/io/flutter/embedding/engine/RenderingComponentTest.java", "test/io/flutter/embedding/engine/dart/DartExecutorTest.java", "test/io/flutter/embedding/engine/dart/DartMessengerTest.java", - "test/io/flutter/embedding/engine/dynamicfeatures/PlayStoreDynamicFeatureManagerTest.java", "test/io/flutter/embedding/engine/loader/ApplicationInfoLoaderTest.java", "test/io/flutter/embedding/engine/loader/FlutterLoaderTest.java", "test/io/flutter/embedding/engine/mutatorsstack/FlutterMutatorViewTest.java", diff --git a/shell/platform/android/embedding_bundle/build.gradle b/shell/platform/android/embedding_bundle/build.gradle index c3eea2b22fbf4..7a60d4c16a24c 100644 --- a/shell/platform/android/embedding_bundle/build.gradle +++ b/shell/platform/android/embedding_bundle/build.gradle @@ -48,12 +48,6 @@ 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" - // 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 diff --git a/shell/platform/android/io/flutter/FlutterInjector.java b/shell/platform/android/io/flutter/FlutterInjector.java index d703007ff968e..23324c7b7fe42 100644 --- a/shell/platform/android/io/flutter/FlutterInjector.java +++ b/shell/platform/android/io/flutter/FlutterInjector.java @@ -5,9 +5,7 @@ package io.flutter; import androidx.annotation.NonNull; -import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; -import io.flutter.embedding.engine.dynamicfeatures.DynamicFeatureManager; import io.flutter.embedding.engine.loader.FlutterLoader; /** @@ -64,14 +62,11 @@ public static void reset() { instance = null; } - private FlutterInjector( - @NonNull FlutterLoader flutterLoader, DynamicFeatureManager dynamicFeatureManager) { + private FlutterInjector(@NonNull FlutterLoader flutterLoader) { this.flutterLoader = flutterLoader; - this.dynamicFeatureManager = dynamicFeatureManager; } private FlutterLoader flutterLoader; - private DynamicFeatureManager dynamicFeatureManager; /** Returns the {@link FlutterLoader} instance to use for the Flutter Android engine embedding. */ @NonNull @@ -79,15 +74,6 @@ public FlutterLoader flutterLoader() { return flutterLoader; } - /** - * Returns the {@link DynamicFeatureManager} instance to use for the Flutter Android engine - * embedding. - */ - @Nullable - public DynamicFeatureManager dynamicFeatureManager() { - return dynamicFeatureManager; - } - /** * Builder used to supply a custom FlutterInjector instance to {@link * FlutterInjector#setInstance(FlutterInjector)}. @@ -96,7 +82,6 @@ public DynamicFeatureManager dynamicFeatureManager() { */ public static final class Builder { private FlutterLoader flutterLoader; - private DynamicFeatureManager dynamicFeatureManager; /** * Sets a {@link FlutterLoader} override. * @@ -107,16 +92,10 @@ public Builder setFlutterLoader(@NonNull FlutterLoader flutterLoader) { return this; } - public Builder setDynamicFeatureManager(@Nullable DynamicFeatureManager dynamicFeatureManager) { - this.dynamicFeatureManager = dynamicFeatureManager; - return this; - } - private void fillDefaults() { if (flutterLoader == null) { flutterLoader = new FlutterLoader(); } - // DynamicFeatureManager's intended default is null. } /** @@ -126,7 +105,7 @@ private void fillDefaults() { public FlutterInjector build() { fillDefaults(); - return new FlutterInjector(flutterLoader, dynamicFeatureManager); + return new FlutterInjector(flutterLoader); } } } diff --git a/shell/platform/android/io/flutter/embedding/engine/FlutterEngine.java b/shell/platform/android/io/flutter/embedding/engine/FlutterEngine.java index 556b4cd3af021..2e001e7a73965 100644 --- a/shell/platform/android/io/flutter/embedding/engine/FlutterEngine.java +++ b/shell/platform/android/io/flutter/embedding/engine/FlutterEngine.java @@ -299,8 +299,6 @@ public FlutterEngine( flutterJNI.addEngineLifecycleListener(engineLifecycleListener); flutterJNI.setPlatformViewsController(platformViewsController); flutterJNI.setLocalizationPlugin(localizationPlugin); - flutterJNI.setDynamicFeatureManager(FlutterInjector.instance().dynamicFeatureManager()); - attachToJni(); // TODO(mattcarroll): FlutterRenderer is temporally coupled to attach(). Remove that coupling if @@ -376,11 +374,7 @@ public void destroy() { platformViewsController.onDetachedFromJNI(); dartExecutor.onDetachedFromJNI(); flutterJNI.removeEngineLifecycleListener(engineLifecycleListener); - flutterJNI.setDynamicFeatureManager(null); flutterJNI.detachFromNativeAndReleaseResources(); - if (FlutterInjector.instance().dynamicFeatureManager() != null) { - FlutterInjector.instance().dynamicFeatureManager().destroy(); - } } /** diff --git a/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java b/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java index 94576fb302f10..604bb0ebc4e2d 100644 --- a/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java +++ b/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java @@ -20,7 +20,6 @@ import io.flutter.Log; import io.flutter.embedding.engine.FlutterEngine.EngineLifecycleListener; import io.flutter.embedding.engine.dart.PlatformMessageHandler; -import io.flutter.embedding.engine.dynamicfeatures.DynamicFeatureManager; import io.flutter.embedding.engine.mutatorsstack.FlutterMutatorsStack; import io.flutter.embedding.engine.renderer.FlutterUiDisplayListener; import io.flutter.embedding.engine.renderer.RenderSurface; @@ -226,8 +225,6 @@ public static native void nativeOnVsync( @Nullable private LocalizationPlugin localizationPlugin; @Nullable private PlatformViewsController platformViewsController; - @Nullable private DynamicFeatureManager dynamicFeatureManager; - @NonNull private final Set engineLifecycleListeners = new CopyOnWriteArraySet<>(); @@ -984,117 +981,6 @@ String[] computePlatformResolvedLocale(@NonNull String[] strings) { // ----- End Localization Support ---- - // ----- Start Dynamic Features Support ---- - - /** Sets the dynamic feature manager that is used to download and install split features. */ - @UiThread - public void setDynamicFeatureManager(@Nullable DynamicFeatureManager dynamicFeatureManager) { - ensureRunningOnMainThread(); - this.dynamicFeatureManager = dynamicFeatureManager; - if (dynamicFeatureManager != null) { - dynamicFeatureManager.setJNI(this); - } - } - - /** - * Called by dart to request that a Dart deferred library corresponding to loadingUnitId be - * downloaded (if necessary) and loaded into the dart vm. - * - *

This method delegates the task to DynamicFeatureManager, which handles the download and - * loading of the dart library and any assets. - * - * @param loadingUnitId The loadingUnitId is assigned during compile time by gen_snapshot and is - * automatically retrieved when loadLibrary() is called on a dart deferred library. - */ - @SuppressWarnings("unused") - @UiThread - public void requestDartDeferredLibrary(int loadingUnitId) { - if (dynamicFeatureManager != null) { - dynamicFeatureManager.downloadDynamicFeature(loadingUnitId, null); - } else { - // TODO(garyq): Add link to setup/instructions guide wiki. - Log.e( - TAG, - "No DynamicFeatureManager found. Android setup must be completed before using split AOT dynamic features."); - } - } - - /** - * Searches each of the provided paths for a valid Dart shared library .so file and resolves - * symbols to load into the dart VM. - * - *

Successful loading of the dart library completes the future returned by loadLibrary() that - * triggered the install/load process. - * - * @param loadingUnitId The loadingUnitId is assigned during compile time by gen_snapshot and is - * automatically retrieved when loadLibrary() is called on a dart deferred library. This is - * used to identify which Dart deferred library the resolved correspond to. - * @param searchPaths An array of paths in which to look for valid dart shared libraries. This - * supports paths within zipped apks as long as the apks are not compressed using the - * `path/to/apk.apk!path/inside/apk/lib.so` format. Paths will be tried first to last and ends - * when a library is sucessfully found. When the found library is invalid, no additional paths - * will be attempted. - */ - @UiThread - public void loadDartDeferredLibrary(int loadingUnitId, @NonNull String[] searchPaths) { - ensureRunningOnMainThread(); - ensureAttachedToNative(); - nativeLoadDartDeferredLibrary(nativePlatformViewId, loadingUnitId, searchPaths); - } - - private native void nativeLoadDartDeferredLibrary( - long nativePlatformViewId, int loadingUnitId, @NonNull String[] searchPaths); - - /** - * Adds the specified AssetManager as an APKAssetResolver in the Flutter Engine's AssetManager. - * - *

This may be used to update the engine AssetManager when a new dynamic feature is installed - * and a new Android AssetManager is created with access to new assets. - * - * @param assetManager An android AssetManager that is able to access the newly downloaded assets. - * @param assetBundlePath The subdirectory that the flutter assets are stored in. The typical - * value is `flutter_assets`. - */ - @UiThread - public void updateAssetManager( - @NonNull AssetManager assetManager, @NonNull String assetBundlePath) { - ensureRunningOnMainThread(); - ensureAttachedToNative(); - nativeUpdateAssetManager(nativePlatformViewId, assetManager, assetBundlePath); - } - - private native void nativeUpdateAssetManager( - long nativePlatformViewId, - @NonNull AssetManager assetManager, - @NonNull String assetBundlePath); - - /** - * Indicates that a failure was encountered during the Android portion of downloading a dynamic - * feature module and loading a dart deferred library, which is typically done by - * DynamicFeatureManager. - * - *

This will inform dart that the future returned by loadLibrary() should complete with an - * error. - * - * @param loadingUnitId The loadingUnitId that corresponds to the dart deferred library that - * failed to install. - * @param error The error message to display. - * @param isTransient When isTransient is false, new attempts to install will automatically result - * in same error in Dart before the request is passed to Android. - */ - @SuppressWarnings("unused") - @UiThread - public void dynamicFeatureInstallFailure( - int loadingUnitId, @NonNull String error, boolean isTransient) { - ensureRunningOnMainThread(); - nativeDynamicFeatureInstallFailure(loadingUnitId, error, isTransient); - } - - private native void nativeDynamicFeatureInstallFailure( - int loadingUnitId, @NonNull String error, boolean isTransient); - - // ----- End Dynamic Features Support ---- - // @SuppressWarnings("unused") @UiThread public void onDisplayPlatformView( diff --git a/shell/platform/android/io/flutter/embedding/engine/dynamicfeatures/DynamicFeatureManager.java b/shell/platform/android/io/flutter/embedding/engine/dynamicfeatures/DynamicFeatureManager.java deleted file mode 100644 index 747f6df01d56f..0000000000000 --- a/shell/platform/android/io/flutter/embedding/engine/dynamicfeatures/DynamicFeatureManager.java +++ /dev/null @@ -1,154 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package io.flutter.embedding.engine.dynamicfeatures; - -import io.flutter.embedding.engine.FlutterJNI; - -// TODO: add links to external documentation on how to use split aot features. -/** - * Basic interface that handles downloading and loading of dynamic features. - * - *

Flutter dynamic feature support is still in early developer preview and should not be used in - * production apps yet. - * - *

The Flutter default implementation is PlayStoreDynamicFeatureManager. - * - *

DynamicFeatureManager handles the embedder/Android level tasks of downloading, installing, and - * loading Dart deferred libraries. A typical code-flow begins with a Dart call to loadLibrary() on - * deferred imported library. See https://dart.dev/guides/language/language-tour#deferred-loading - * This call retrieves a unique identifier called the loading unit id, which is assigned by - * gen_snapshot during compilation. The loading unit id is passed down through the engine and - * invokes downloadDynamicFeature. Once the feature module is downloaded, loadAssets and - * loadDartLibrary should be invoked. loadDartLibrary should find shared library .so files for the - * engine to open and pass the .so path to FlutterJNI.loadDartDeferredLibrary. loadAssets should - * typically ensure the new assets are available to the engine's asset manager by passing an updated - * Android AssetManager to the engine via FlutterJNI.updateAssetManager. - * - *

The loadAssets and loadDartLibrary methods are separated out because they may also be called - * manually via platform channel messages. A full downloadDynamicFeature implementation should call - * these two methods as needed. - * - *

A dynamic feature module is uniquely identified by a module name as defined in - * bundle_config.yaml. Each feature module may contain one or more loading units, uniquely - * identified by the loading unit ID and assets. - */ -public interface DynamicFeatureManager { - /** - * Sets the FlutterJNI to be used to communication with the Flutter native engine. - * - *

A FlutterJNI is required in order to properly execute loadAssets and loadDartLibrary. - * - *

Since this class may be instantiated for injection before the FlutterEngine and FlutterJNI - * is fully initialized, this method should be called to provide the FlutterJNI instance to use - * for use in loadDartLibrary and loadAssets. - */ - public abstract void setJNI(FlutterJNI flutterJNI); - - /** - * Request that the feature module be downloaded and installed. - * - *

This method begins the download and installation of the specified feature module. For - * example, the Play Store dynamic delivery implementation uses SplitInstallManager to request the - * download of the module. Download is not complete when this method returns. The download process - * should be listened for and upon completion of download, listeners should invoke loadAssets - * first and then loadDartLibrary to complete the dynamic feature load process. - * - *

Both parameters are not always necessary to identify which module to install. Asset-only - * modules do not have an associated loadingUnitId. Instead, an invalid ID like -1 may be passed - * to download only with moduleName. On the other hand, it can be possible to resolve the - * moduleName based on the loadingUnitId. This resolution is done if moduleName is null. At least - * one of loadingUnitId or moduleName must be valid or non-null. - * - *

Flutter will typically call this method in two ways. When invoked as part of a dart - * loadLibrary() call, a valid loadingUnitId is passed in while the moduleName is null. In this - * case, this method is responsible for figuring out what module the loadingUnitId corresponds to. - * - *

When invoked manually as part of loading an assets-only module, loadingUnitId is -1 - * (invalid) and moduleName is supplied. Without a loadingUnitId, this method just downloads the - * module by name and attempts to load assets via loadAssets. - * - * @param loadingUnitId The unique identifier associated with a Dart deferred library. This id is - * assigned by the compiler and can be seen for reference in bundle_config.yaml. This ID is - * primarily used in loadDartLibrary to indicate to Dart which Dart library is being loaded. - * Loading unit ids range from 0 to the number existing loading units. Passing a negative - * loading unit id indicates that no Dart deferred library should be loaded after download - * completes. This is the case when the dynamic feature module is an assets-only module. If a - * negative loadingUnitId is passed, then moduleName must not be null. Passing a loadingUnitId - * larger than the highest valid loading unit's id will cause the Dart loadLibrary() to - * complete with a failure. - * @param moduleName The dynamic feature module name as defined in bundle_config.yaml. This may be - * null if the dynamic feature to be loaded is associated with a loading unit/deferred dart - * library. In this case, it is this method's responsibility to map the loadingUnitId to its - * corresponding moduleName. When loading asset-only or other dynamic features without an - * associated Dart deferred library, loading unit id should a negative value and moduleName - * must be non-null. - */ - public abstract void downloadDynamicFeature(int loadingUnitId, String moduleName); - - /** - * Extract and load any assets and resources from the module for use by Flutter. - * - *

This method should provide a refreshed AssetManager to FlutterJNI.updateAssetManager that - * can access the new assets. If no assets are included as part of the dynamic feature, then - * nothing needs to be done. - * - *

If using the Play Store dynamic feature delivery, refresh the context via: {@code - * context.createPackageContext(context.getPackageName(), 0);} This returns a new context, from - * which an updated asset manager may be obtained and passed to updateAssetManager in FlutterJNI. - * This process does not require loadingUnitId or moduleName, however, the two parameters are - * still present for custom implementations that store assets outside of Android's native system. - * - *

Assets shoud be loaded before the Dart deferred library is loaded, as successful loading of - * the Dart loading unit indicates the dynamic feature is fully loaded. Implementations of - * downloadDynamicFeature should invoke this after successful download. - * - * @param loadingUnitId The unique identifier associated with a Dart deferred library. - * @param moduleName The dynamic feature module name as defined in bundle_config.yaml. - */ - public abstract void loadAssets(int loadingUnitId, String moduleName); - - /** - * Load the .so shared library file into the Dart VM. - * - *

When the download of a dynamic feature module completes, this method should be called to - * find the path .so library file. The path(s) should then be passed to - * FlutterJNI.loadDartDeferredLibrary to be dlopen-ed and loaded into the Dart VM. - * - *

Specifically, APKs distributed by Android's app bundle format may vary by device and API - * number, so FlutterJNI's loadDartDeferredLibrary accepts a list of search paths with can include - * paths within APKs that have not been unpacked using the - * `path/to/apk.apk!path/inside/apk/lib.so` format. Each search path will be attempted in order - * until a shared library is found. This allows for the developer to avoid unpacking the apk zip. - * - *

Upon successful load of the Dart library, the Dart future from the originating loadLibary() - * call completes and developers are able to use symbols and assets from the feature module. - * - * @param loadingUnitId The unique identifier associated with a Dart deferred library. This id is - * assigned by the compiler and can be seen for reference in bundle_config.yaml. This ID is - * primarily used in loadDartLibrary to indicate to Dart which Dart library is being loaded. - * Loading unit ids range from 0 to the number existing loading units. Negative loading unit - * ids are considered invalid and this method will result in a no-op. - * @param moduleName The dynamic feature module name as defined in bundle_config.yaml. If using - * Play Store dynamic feature delivery, this name corresponds to the root name on the - * installed APKs in which to search for the desired shared library .so file. - */ - public abstract void loadDartLibrary(int loadingUnitId, String moduleName); - - /** - * Uninstall the specified feature module. - * - *

Both parameters are not always necessary to identify which module to uninstall. Asset-only - * modules do not have an associated loadingUnitId. Instead, an invalid ID like -1 may be passed - * to download only with moduleName. On the other hand, it can be possible to resolve the - * moduleName based on the loadingUnitId. This resolution is done if moduleName is null. At least - * one of loadingUnitId or moduleName must be valid or non-null. - */ - public abstract void uninstallFeature(int loadingUnitId, String moduleName); - - /** - * Cleans up and releases resources. This object is no longer usable after calling this method. - */ - public abstract void destroy(); -} diff --git a/shell/platform/android/io/flutter/embedding/engine/dynamicfeatures/PlayStoreDynamicFeatureManager.java b/shell/platform/android/io/flutter/embedding/engine/dynamicfeatures/PlayStoreDynamicFeatureManager.java deleted file mode 100644 index de613cacbcf2f..0000000000000 --- a/shell/platform/android/io/flutter/embedding/engine/dynamicfeatures/PlayStoreDynamicFeatureManager.java +++ /dev/null @@ -1,339 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package io.flutter.embedding.engine.dynamicfeatures; - -import android.content.Context; -import android.content.pm.PackageManager.NameNotFoundException; -import android.content.res.AssetManager; -import android.os.Build; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import com.google.android.play.core.splitinstall.SplitInstallException; -import com.google.android.play.core.splitinstall.SplitInstallManager; -import com.google.android.play.core.splitinstall.SplitInstallManagerFactory; -import com.google.android.play.core.splitinstall.SplitInstallRequest; -import com.google.android.play.core.splitinstall.SplitInstallSessionState; -import com.google.android.play.core.splitinstall.SplitInstallStateUpdatedListener; -import com.google.android.play.core.splitinstall.model.SplitInstallErrorCode; -import com.google.android.play.core.splitinstall.model.SplitInstallSessionStatus; -import io.flutter.Log; -import io.flutter.embedding.engine.FlutterJNI; -import java.io.File; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Queue; - -/** - * Flutter default implementation of DynamicFeatureManager that downloads dynamic feature modules - * from the Google Play store. - */ -public class PlayStoreDynamicFeatureManager implements DynamicFeatureManager { - private static final String TAG = "PlayStoreDynamicFeatureManager"; - - private @NonNull SplitInstallManager splitInstallManager; - private @Nullable FlutterJNI flutterJNI; - private @NonNull Context context; - // Each request to install a feature module gets a session ID. These maps associate - // the session ID with the loading unit and module name that was requested. - private @NonNull Map sessionIdToName; - private @NonNull Map sessionIdToLoadingUnitId; - - private FeatureInstallStateUpdatedListener listener; - - private class FeatureInstallStateUpdatedListener implements SplitInstallStateUpdatedListener { - public void onStateUpdate(SplitInstallSessionState state) { - if (sessionIdToName.containsKey(state.sessionId())) { - // TODO(garyq): Add system channel for split aot messages. - switch (state.status()) { - case SplitInstallSessionStatus.FAILED: - { - Log.e( - TAG, - String.format( - "Module \"%s\" (sessionId %d) install failed with: %s", - sessionIdToName.get(state.sessionId()), - state.sessionId(), - state.errorCode())); - flutterJNI.dynamicFeatureInstallFailure( - sessionIdToLoadingUnitId.get(state.sessionId()), - "Module install failed with " + state.errorCode(), - true); - sessionIdToName.remove(state.sessionId()); - sessionIdToLoadingUnitId.remove(state.sessionId()); - break; - } - case SplitInstallSessionStatus.INSTALLED: - { - Log.d( - TAG, - String.format( - "Module \"%s\" (sessionId %d) install successfully.", - sessionIdToName.get(state.sessionId()), state.sessionId())); - loadAssets( - sessionIdToLoadingUnitId.get(state.sessionId()), - sessionIdToName.get(state.sessionId())); - // We only load Dart shared lib for the loading unit id requested. Other loading units - // (if present) in the dynamic feature module are not loaded, but can be loaded by - // calling again with their loading unit id. - loadDartLibrary( - sessionIdToLoadingUnitId.get(state.sessionId()), - sessionIdToName.get(state.sessionId())); - sessionIdToName.remove(state.sessionId()); - sessionIdToLoadingUnitId.remove(state.sessionId()); - break; - } - case SplitInstallSessionStatus.CANCELED: - { - Log.d( - TAG, - String.format( - "Module \"%s\" (sessionId %d) install canceled.", - sessionIdToName.get(state.sessionId()), state.sessionId())); - sessionIdToName.remove(state.sessionId()); - break; - } - case SplitInstallSessionStatus.CANCELING: - { - Log.d( - TAG, - String.format( - "Module \"%s\" (sessionId %d) install canceling.", - sessionIdToName.get(state.sessionId()), state.sessionId())); - break; - } - case SplitInstallSessionStatus.PENDING: - { - Log.d( - TAG, - String.format( - "Module \"%s\" (sessionId %d) install pending.", - sessionIdToName.get(state.sessionId()), state.sessionId())); - break; - } - case SplitInstallSessionStatus.REQUIRES_USER_CONFIRMATION: - { - Log.d( - TAG, - String.format( - "Module \"%s\" (sessionId %d) install requires user confirmation.", - sessionIdToName.get(state.sessionId()), state.sessionId())); - break; - } - case SplitInstallSessionStatus.DOWNLOADING: - { - Log.d( - TAG, - String.format( - "Module \"%s\" (sessionId %d) downloading.", - sessionIdToName.get(state.sessionId()), state.sessionId())); - break; - } - case SplitInstallSessionStatus.DOWNLOADED: - { - Log.d( - TAG, - String.format( - "Module \"%s\" (sessionId %d) downloaded.", - sessionIdToName.get(state.sessionId()), state.sessionId())); - break; - } - case SplitInstallSessionStatus.INSTALLING: - { - Log.d( - TAG, - String.format( - "Module \"%s\" (sessionId %d) installing.", - sessionIdToName.get(state.sessionId()), state.sessionId())); - break; - } - default: - Log.d(TAG, "Status: " + state.status()); - } - } - } - } - - public PlayStoreDynamicFeatureManager(@NonNull Context context, @Nullable FlutterJNI flutterJNI) { - this.context = context; - this.flutterJNI = flutterJNI; - splitInstallManager = SplitInstallManagerFactory.create(context); - listener = new FeatureInstallStateUpdatedListener(); - splitInstallManager.registerListener(listener); - sessionIdToName = new HashMap(); - sessionIdToLoadingUnitId = new HashMap(); - } - - public void setJNI(@NonNull FlutterJNI flutterJNI) { - this.flutterJNI = flutterJNI; - } - - private boolean verifyJNI() { - if (flutterJNI == null) { - Log.e( - TAG, - "No FlutterJNI provided. `setJNI` must be called on the DynamicFeatureManager before attempting to load dart libraries or invoking with platform channels."); - return false; - } - return true; - } - - private String loadingUnitIdToModuleName(int loadingUnitId) { - // Loading unit id to module name mapping stored in android Strings - // resources. - int moduleNameIdentifier = - context - .getResources() - .getIdentifier("loadingUnit" + loadingUnitId, "string", context.getPackageName()); - return context.getResources().getString(moduleNameIdentifier); - } - - public void downloadDynamicFeature(int loadingUnitId, String moduleName) { - String resolvedModuleName = - moduleName == null ? moduleName : loadingUnitIdToModuleName(loadingUnitId); - if (resolvedModuleName == null) { - Log.d(TAG, "Dynamic feature module name was null."); - return; - } - - SplitInstallRequest request = SplitInstallRequest.newBuilder().addModule(moduleName).build(); - - splitInstallManager - // Submits the request to install the module through the - // asynchronous startInstall() task. Your app needs to be - // in the foreground to submit the request. - .startInstall(request) - // Called when the install request is sent successfully. This is different than a successful - // install which is handled in FeatureInstallStateUpdatedListener. - .addOnSuccessListener( - sessionId -> { - this.sessionIdToName.put(sessionId, moduleName); - this.sessionIdToLoadingUnitId.put(sessionId, loadingUnitId); - }) - .addOnFailureListener( - exception -> { - switch (((SplitInstallException) exception).getErrorCode()) { - case SplitInstallErrorCode.NETWORK_ERROR: - flutterJNI.dynamicFeatureInstallFailure( - loadingUnitId, - String.format( - "Install of dynamic feature module \"%s\" failed with a network error", - moduleName), - true); - break; - case SplitInstallErrorCode.MODULE_UNAVAILABLE: - flutterJNI.dynamicFeatureInstallFailure( - loadingUnitId, - String.format( - "Install of dynamic feature module \"%s\" failed as it is unavailable", - moduleName), - false); - break; - default: - flutterJNI.dynamicFeatureInstallFailure( - loadingUnitId, - String.format( - "Install of dynamic feature module \"%s\" failed with error %d: %s", - moduleName, - ((SplitInstallException) exception).getErrorCode(), - ((SplitInstallException) exception).getMessage()), - false); - break; - } - }); - } - - public void loadAssets(int loadingUnitId, String moduleName) { - if (!verifyJNI()) { - return; - } - // Since android dynamic feature asset manager is handled through - // context, neither parameter is used here. Assets are stored in - // the apk's `assets` directory allowing them to be accessed by - // Android's AssetManager directly. - try { - context = context.createPackageContext(context.getPackageName(), 0); - - AssetManager assetManager = context.getAssets(); - flutterJNI.updateAssetManager( - assetManager, - // TODO(garyq): Made the "flutter_assets" directory dynamic based off of DartEntryPoint. - "flutter_assets"); - } catch (NameNotFoundException e) { - throw new RuntimeException(e); - } - } - - public void loadDartLibrary(int loadingUnitId, String moduleName) { - if (!verifyJNI()) { - return; - } - // Loading unit must be specified and valid to load a dart library. - if (loadingUnitId < 0) { - return; - } - - // This matches/depends on dart's loading unit naming convention, which we use unchanged. - String aotSharedLibraryName = "app.so-" + loadingUnitId + ".part.so"; - - // Possible values: armeabi, armeabi-v7a, arm64-v8a, x86, x86_64, mips, mips64 - String abi; - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - abi = Build.SUPPORTED_ABIS[0]; - } else { - abi = Build.CPU_ABI; - } - String pathAbi = abi.replace("-", "_"); // abis are represented with underscores in paths. - - // TODO(garyq): Optimize this apk/file discovery process to use less i/o and be more - // performant and robust. - - // Search directly in APKs first - List apkPaths = new ArrayList(); - // If not found in APKs, we check in extracted native libs for the lib directly. - List soPaths = new ArrayList(); - Queue searchFiles = new LinkedList(); - searchFiles.add(context.getFilesDir()); - while (!searchFiles.isEmpty()) { - File file = searchFiles.remove(); - if (file != null && file.isDirectory()) { - for (File f : file.listFiles()) { - searchFiles.add(f); - } - continue; - } - String name = file.getName(); - if (name.endsWith(".apk") && name.startsWith(moduleName) && name.contains(pathAbi)) { - apkPaths.add(file.getAbsolutePath()); - continue; - } - if (name.equals(aotSharedLibraryName)) { - soPaths.add(file.getAbsolutePath()); - } - } - - List searchPaths = new ArrayList(); - for (String path : apkPaths) { - searchPaths.add(path + "!lib/" + abi + "/" + aotSharedLibraryName); - } - for (String path : soPaths) { - searchPaths.add(path); - } - - flutterJNI.loadDartDeferredLibrary( - loadingUnitId, searchPaths.toArray(new String[apkPaths.size()])); - } - - public void uninstallFeature(int loadingUnitId, String moduleName) { - // TODO(garyq): support uninstalling. - } - - public void destroy() { - splitInstallManager.unregisterListener(listener); - flutterJNI = null; - } -} diff --git a/shell/platform/android/jni/jni_mock.h b/shell/platform/android/jni/jni_mock.h index 52b38e1e84308..65f790d972ee8 100644 --- a/shell/platform/android/jni/jni_mock.h +++ b/shell/platform/android/jni/jni_mock.h @@ -95,11 +95,6 @@ class JNIMock final : public PlatformViewAndroidJNI { (override)); MOCK_METHOD(double, GetDisplayRefreshRate, (), (override)); - - MOCK_METHOD(bool, - RequestDartDeferredLibrary, - (int loading_unit_id), - (override)); }; } // namespace flutter diff --git a/shell/platform/android/jni/platform_view_android_jni.h b/shell/platform/android/jni/platform_view_android_jni.h index 81323605de68c..e06079c1f5c4f 100644 --- a/shell/platform/android/jni/platform_view_android_jni.h +++ b/shell/platform/android/jni/platform_view_android_jni.h @@ -195,8 +195,6 @@ class PlatformViewAndroidJNI { std::vector supported_locales_data) = 0; virtual double GetDisplayRefreshRate() = 0; - - virtual bool RequestDartDeferredLibrary(int loading_unit_id) = 0; }; } // namespace flutter diff --git a/shell/platform/android/platform_view_android.cc b/shell/platform/android/platform_view_android.cc index f5049b23223d6..8b6b27658b621 100644 --- a/shell/platform/android/platform_view_android.cc +++ b/shell/platform/android/platform_view_android.cc @@ -336,29 +336,6 @@ PlatformViewAndroid::ComputePlatformResolvedLocales( supported_locale_data); } -// |PlatformView| -void PlatformViewAndroid::RequestDartDeferredLibrary(intptr_t loading_unit_id) { - if (jni_facade_->RequestDartDeferredLibrary(loading_unit_id)) { - return; - } - return; // TODO(garyq): Call LoadDartDeferredLibraryFailure() -} - -// |PlatformView| -void PlatformViewAndroid::LoadDartDeferredLibrary( - intptr_t loading_unit_id, - const uint8_t* snapshot_data, - const uint8_t* snapshot_instructions) { - delegate_.LoadDartDeferredLibrary(loading_unit_id, snapshot_data, - snapshot_instructions); -} - -// |PlatformView| -void PlatformViewAndroid::UpdateAssetManager( - std::shared_ptr asset_manager) { - delegate_.UpdateAssetManager(std::move(asset_manager)); -} - void PlatformViewAndroid::InstallFirstFrameCallback() { // On Platform Task Runner. SetNextFrameCallback( diff --git a/shell/platform/android/platform_view_android.h b/shell/platform/android/platform_view_android.h index ff2ac1353f2b3..3b424f2920a6f 100644 --- a/shell/platform/android/platform_view_android.h +++ b/shell/platform/android/platform_view_android.h @@ -93,14 +93,6 @@ class PlatformViewAndroid final : public PlatformView { int64_t texture_id, const fml::jni::JavaObjectWeakGlobalRef& surface_texture); - // |PlatformView| - void LoadDartDeferredLibrary(intptr_t loading_unit_id, - const uint8_t* snapshot_data, - const uint8_t* snapshot_instructions) override; - - // |PlatformView| - void UpdateAssetManager(std::shared_ptr asset_manager) override; - private: const std::shared_ptr jni_facade_; std::unique_ptr android_context_; @@ -145,9 +137,6 @@ class PlatformViewAndroid final : public PlatformView { std::unique_ptr> ComputePlatformResolvedLocales( const std::vector& supported_locale_data) override; - // |PlatformView| - void RequestDartDeferredLibrary(intptr_t loading_unit_id) override; - void InstallFirstFrameCallback(); void FireFirstFrameCallback(); diff --git a/shell/platform/android/platform_view_android_jni_impl.cc b/shell/platform/android/platform_view_android_jni_impl.cc index a252d167b07c3..084872a023313 100644 --- a/shell/platform/android/platform_view_android_jni_impl.cc +++ b/shell/platform/android/platform_view_android_jni_impl.cc @@ -5,9 +5,7 @@ #include "flutter/shell/platform/android/platform_view_android_jni_impl.h" #include -#include #include -#include #include #include "unicode/uchar.h" @@ -102,8 +100,6 @@ static jmethodID g_detach_from_gl_context_method = nullptr; static jmethodID g_compute_platform_resolved_locale_method = nullptr; -static jmethodID g_request_dart_deferred_library_method = nullptr; - // Called By Java static jmethodID g_on_display_platform_view_method = nullptr; @@ -512,108 +508,6 @@ static jboolean FlutterTextUtilsIsRegionalIndicator(JNIEnv* env, jint codePoint) { return u_hasBinaryProperty(codePoint, UProperty::UCHAR_REGIONAL_INDICATOR); } - -static void LoadLoadingUnitFailure(intptr_t loading_unit_id, - std::string message, - bool transient) { - // TODO(garyq): Implement -} - -static void DynamicFeatureInstallFailure(JNIEnv* env, - jobject obj, - jint jLoadingUnitId, - jstring jError, - jboolean jTransient) { - LoadLoadingUnitFailure(static_cast(jLoadingUnitId), - fml::jni::JavaStringToString(env, jError), - static_cast(jTransient)); -} - -static void LoadDartDeferredLibrary(JNIEnv* env, - jobject obj, - jlong shell_holder, - jint jLoadingUnitId, - jobjectArray jSearchPaths) { - // Convert java->c++ - intptr_t loading_unit_id = static_cast(jLoadingUnitId); - std::vector search_paths = - fml::jni::StringArrayToVector(env, jSearchPaths); - - // TODO: Switch to using the NativeLibrary class, eg: - // - // fml::RefPtr native_lib = - // fml::NativeLibrary::Create(lib_name.c_str()); - // - // Find and open the shared library. - void* handle = nullptr; - while (handle == nullptr && !search_paths.empty()) { - std::string path = search_paths.back(); - handle = ::dlopen(path.c_str(), RTLD_NOW); - search_paths.pop_back(); - } - if (handle == nullptr) { - LoadLoadingUnitFailure(loading_unit_id, - "No lib .so found for provided search paths.", true); - return; - } - - // Resolve symbols. - uint8_t* isolate_data = - static_cast(::dlsym(handle, DartSnapshot::kIsolateDataSymbol)); - if (isolate_data == nullptr) { - // Mac sometimes requires an underscore prefix. - std::stringstream underscore_symbol_name; - underscore_symbol_name << "_" << DartSnapshot::kIsolateDataSymbol; - isolate_data = static_cast( - ::dlsym(handle, underscore_symbol_name.str().c_str())); - if (isolate_data == nullptr) { - LoadLoadingUnitFailure(loading_unit_id, - "Could not resolve data symbol in library", true); - return; - } - } - uint8_t* isolate_instructions = static_cast( - ::dlsym(handle, DartSnapshot::kIsolateInstructionsSymbol)); - if (isolate_instructions == nullptr) { - // Mac sometimes requires an underscore prefix. - std::stringstream underscore_symbol_name; - underscore_symbol_name << "_" << DartSnapshot::kIsolateInstructionsSymbol; - isolate_instructions = static_cast( - ::dlsym(handle, underscore_symbol_name.str().c_str())); - if (isolate_data == nullptr) { - LoadLoadingUnitFailure(loading_unit_id, - "Could not resolve instructions symbol in library", - true); - return; - } - } - - ANDROID_SHELL_HOLDER->GetPlatformView()->LoadDartDeferredLibrary( - loading_unit_id, isolate_data, isolate_instructions); - - // TODO(garyq): fallback on soPath. -} - -// TODO(garyq): persist additional asset resolvers by updating instead of -// replacing with newly created asset_manager -static void UpdateAssetManager(JNIEnv* env, - jobject obj, - jlong shell_holder, - jobject jAssetManager, - jstring jAssetBundlePath) { - auto asset_manager = std::make_shared(); - asset_manager->PushBack(std::make_unique( - env, // jni environment - jAssetManager, // asset manager - fml::jni::JavaStringToString(env, jAssetBundlePath)) // apk asset dir - ); - // Create config to set persistent cache asset manager - RunConfiguration config(nullptr, std::move(asset_manager)); - - ANDROID_SHELL_HOLDER->GetPlatformView()->UpdateAssetManager( - config.GetAssetManager()); -} - bool RegisterApi(JNIEnv* env) { static const JNINativeMethod flutter_jni_methods[] = { // Start of methods from FlutterJNI @@ -770,22 +664,6 @@ bool RegisterApi(JNIEnv* env) { .fnPtr = reinterpret_cast(&FlutterTextUtilsIsRegionalIndicator), }, - { - .name = "nativeLoadDartDeferredLibrary", - .signature = "(JI[Ljava/lang/String;)V", - .fnPtr = reinterpret_cast(&LoadDartDeferredLibrary), - }, - { - .name = "nativeUpdateAssetManager", - .signature = - "(JLandroid/content/res/AssetManager;Ljava/lang/String;)V", - .fnPtr = reinterpret_cast(&UpdateAssetManager), - }, - { - .name = "nativeDynamicFeatureInstallFailure", - .signature = "(ILjava/lang/String;Z)V", - .fnPtr = reinterpret_cast(&DynamicFeatureInstallFailure), - }, }; if (env->RegisterNatives(g_flutter_jni_class->obj(), flutter_jni_methods, @@ -1029,14 +907,6 @@ bool PlatformViewAndroid::Register(JNIEnv* env) { return false; } - g_request_dart_deferred_library_method = env->GetMethodID( - g_flutter_jni_class->obj(), "requestDartDeferredLibrary", "(I)V"); - - if (g_request_dart_deferred_library_method == nullptr) { - FML_LOG(ERROR) << "Could not locate requestDartDeferredLibrary method"; - return false; - } - return RegisterApi(env); } @@ -1464,21 +1334,4 @@ double PlatformViewAndroidJNIImpl::GetDisplayRefreshRate() { return static_cast(env->GetStaticFloatField(clazz, fid)); } -bool PlatformViewAndroidJNIImpl::RequestDartDeferredLibrary( - int loading_unit_id) { - JNIEnv* env = fml::jni::AttachCurrentThread(); - - auto java_object = java_object_.get(env); - if (java_object.is_null()) { - return true; - } - - env->CallObjectMethod(java_object.obj(), - g_request_dart_deferred_library_method, - loading_unit_id); - - FML_CHECK(CheckException(env)); - return true; -} - } // namespace flutter diff --git a/shell/platform/android/platform_view_android_jni_impl.h b/shell/platform/android/platform_view_android_jni_impl.h index 8fe0618929e95..313a9ee921e6c 100644 --- a/shell/platform/android/platform_view_android_jni_impl.h +++ b/shell/platform/android/platform_view_android_jni_impl.h @@ -80,8 +80,6 @@ class PlatformViewAndroidJNIImpl final : public PlatformViewAndroidJNI { double GetDisplayRefreshRate() override; - bool RequestDartDeferredLibrary(int loading_unit_id) override; - private: // Reference to FlutterJNI object. const fml::jni::JavaObjectWeakGlobalRef java_object_; diff --git a/shell/platform/android/test/io/flutter/FlutterInjectorTest.java b/shell/platform/android/test/io/flutter/FlutterInjectorTest.java index 66384fcb7c27c..9809095a0746d 100644 --- a/shell/platform/android/test/io/flutter/FlutterInjectorTest.java +++ b/shell/platform/android/test/io/flutter/FlutterInjectorTest.java @@ -6,10 +6,8 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; import static org.junit.Assert.assertThrows; -import io.flutter.embedding.engine.dynamicfeatures.PlayStoreDynamicFeatureManager; import io.flutter.embedding.engine.loader.FlutterLoader; import org.junit.Before; import org.junit.Test; @@ -23,7 +21,6 @@ @RunWith(RobolectricTestRunner.class) public class FlutterInjectorTest { @Mock FlutterLoader mockFlutterLoader; - @Mock PlayStoreDynamicFeatureManager mockDynamicFeatureManager; @Before public void setUp() { @@ -37,7 +34,6 @@ public void itHasSomeReasonableDefaults() { // Implicitly builds when first accessed. FlutterInjector injector = FlutterInjector.instance(); assertNotNull(injector.flutterLoader()); - assertNull(injector.dynamicFeatureManager()); } @Test @@ -48,14 +44,6 @@ public void canPartiallyOverride() { assertEquals(injector.flutterLoader(), mockFlutterLoader); } - @Test - public void canInjectDynamicFeatureManager() { - FlutterInjector.setInstance( - new FlutterInjector.Builder().setDynamicFeatureManager(mockDynamicFeatureManager).build()); - FlutterInjector injector = FlutterInjector.instance(); - assertEquals(injector.dynamicFeatureManager(), mockDynamicFeatureManager); - } - @Test() public void cannotBeChangedOnceRead() { FlutterInjector.instance(); diff --git a/shell/platform/android/test/io/flutter/FlutterTestSuite.java b/shell/platform/android/test/io/flutter/FlutterTestSuite.java index 8a7332d9a0ad0..635b6680475d0 100644 --- a/shell/platform/android/test/io/flutter/FlutterTestSuite.java +++ b/shell/platform/android/test/io/flutter/FlutterTestSuite.java @@ -18,7 +18,6 @@ import io.flutter.embedding.engine.RenderingComponentTest; import io.flutter.embedding.engine.dart.DartExecutorTest; import io.flutter.embedding.engine.dart.DartMessengerTest; -import io.flutter.embedding.engine.dynamicfeatures.PlayStoreDynamicFeatureManagerTest; import io.flutter.embedding.engine.loader.ApplicationInfoLoaderTest; import io.flutter.embedding.engine.loader.FlutterLoaderTest; import io.flutter.embedding.engine.mutatorsstack.FlutterMutatorViewTest; @@ -78,7 +77,6 @@ PlatformChannelTest.class, PlatformPluginTest.class, PlatformViewsControllerTest.class, - PlayStoreDynamicFeatureManagerTest.class, PluginComponentTest.class, PreconditionsTest.class, RenderingComponentTest.class, diff --git a/shell/platform/android/test/io/flutter/embedding/engine/dynamicfeatures/PlayStoreDynamicFeatureManagerTest.java b/shell/platform/android/test/io/flutter/embedding/engine/dynamicfeatures/PlayStoreDynamicFeatureManagerTest.java deleted file mode 100644 index 1fafbb3437890..0000000000000 --- a/shell/platform/android/test/io/flutter/embedding/engine/dynamicfeatures/PlayStoreDynamicFeatureManagerTest.java +++ /dev/null @@ -1,166 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package io.flutter.embedding.engine.dynamicfeatures; - -import static junit.framework.TestCase.assertEquals; -import static junit.framework.TestCase.assertTrue; -import static org.mockito.Mockito.any; -import static org.mockito.Mockito.anyInt; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.spy; - -import android.content.Context; -import android.content.pm.PackageManager.NameNotFoundException; -import android.content.res.AssetManager; -import androidx.annotation.NonNull; -import io.flutter.embedding.engine.FlutterJNI; -import java.io.File; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.robolectric.RobolectricTestRunner; -import org.robolectric.RuntimeEnvironment; -import org.robolectric.annotation.Config; - -@Config(manifest = Config.NONE) -@RunWith(RobolectricTestRunner.class) -public class PlayStoreDynamicFeatureManagerTest { - private class TestFlutterJNI extends FlutterJNI { - public int loadDartDeferredLibraryCalled = 0; - public int updateAssetManagerCalled = 0; - public int dynamicFeatureInstallFailureCalled = 0; - public String[] searchPaths; - public int loadingUnitId; - public AssetManager assetManager; - - public TestFlutterJNI() {} - - @Override - public void loadDartDeferredLibrary(int loadingUnitId, @NonNull String[] searchPaths) { - loadDartDeferredLibraryCalled++; - this.searchPaths = searchPaths; - this.loadingUnitId = loadingUnitId; - } - - @Override - public void updateAssetManager( - @NonNull AssetManager assetManager, @NonNull String assetBundlePath) { - updateAssetManagerCalled++; - this.loadingUnitId = loadingUnitId; - this.assetManager = assetManager; - } - - @Override - public void dynamicFeatureInstallFailure( - int loadingUnitId, @NonNull String error, boolean isTransient) { - dynamicFeatureInstallFailureCalled++; - } - } - - // Skips the download process to directly call the loadAssets and loadDartLibrary methods. - private class TestPlayStoreDynamicFeatureManager extends PlayStoreDynamicFeatureManager { - public TestPlayStoreDynamicFeatureManager(Context context, FlutterJNI jni) { - super(context, jni); - } - - @Override - public void downloadDynamicFeature(int loadingUnitId, String moduleName) { - // Override this to skip the online SplitInstallManager portion. - loadAssets(loadingUnitId, moduleName); - loadDartLibrary(loadingUnitId, moduleName); - } - } - - @Test - public void downloadCallsJNIFunctions() throws NameNotFoundException { - TestFlutterJNI jni = new TestFlutterJNI(); - Context spyContext = spy(RuntimeEnvironment.systemContext); - doReturn(spyContext).when(spyContext).createPackageContext(any(), anyInt()); - doReturn(null).when(spyContext).getAssets(); - String soTestPath = "test/path/app.so-123.part.so"; - doReturn(new File(soTestPath)).when(spyContext).getFilesDir(); - TestPlayStoreDynamicFeatureManager playStoreManager = - new TestPlayStoreDynamicFeatureManager(spyContext, jni); - jni.setDynamicFeatureManager(playStoreManager); - assertEquals(jni.loadingUnitId, 0); - - playStoreManager.downloadDynamicFeature(123, "TestModuleName"); - assertEquals(jni.loadDartDeferredLibraryCalled, 1); - assertEquals(jni.updateAssetManagerCalled, 1); - assertEquals(jni.dynamicFeatureInstallFailureCalled, 0); - - assertTrue(jni.searchPaths[0].endsWith(soTestPath)); - assertEquals(jni.searchPaths.length, 1); - assertEquals(jni.loadingUnitId, 123); - } - - @Test - public void searchPathsAddsApks() throws NameNotFoundException { - TestFlutterJNI jni = new TestFlutterJNI(); - Context spyContext = spy(RuntimeEnvironment.systemContext); - doReturn(spyContext).when(spyContext).createPackageContext(any(), anyInt()); - doReturn(null).when(spyContext).getAssets(); - String apkTestPath = "test/path/TestModuleName_armeabi_v7a.apk"; - doReturn(new File(apkTestPath)).when(spyContext).getFilesDir(); - TestPlayStoreDynamicFeatureManager playStoreManager = - new TestPlayStoreDynamicFeatureManager(spyContext, jni); - jni.setDynamicFeatureManager(playStoreManager); - - assertEquals(jni.loadingUnitId, 0); - - playStoreManager.downloadDynamicFeature(123, "TestModuleName"); - assertEquals(jni.loadDartDeferredLibraryCalled, 1); - assertEquals(jni.updateAssetManagerCalled, 1); - assertEquals(jni.dynamicFeatureInstallFailureCalled, 0); - - assertTrue(jni.searchPaths[0].endsWith(apkTestPath + "!lib/armeabi-v7a/app.so-123.part.so")); - assertEquals(jni.searchPaths.length, 1); - assertEquals(jni.loadingUnitId, 123); - } - - @Test - public void invalidSearchPathsAreIgnored() throws NameNotFoundException { - TestFlutterJNI jni = new TestFlutterJNI(); - Context spyContext = spy(RuntimeEnvironment.systemContext); - doReturn(spyContext).when(spyContext).createPackageContext(any(), anyInt()); - doReturn(null).when(spyContext).getAssets(); - String apkTestPath = "test/path/invalidpath.apk"; - doReturn(new File(apkTestPath)).when(spyContext).getFilesDir(); - TestPlayStoreDynamicFeatureManager playStoreManager = - new TestPlayStoreDynamicFeatureManager(spyContext, jni); - jni.setDynamicFeatureManager(playStoreManager); - - assertEquals(jni.loadingUnitId, 0); - - playStoreManager.downloadDynamicFeature(123, "TestModuleName"); - assertEquals(jni.loadDartDeferredLibraryCalled, 1); - assertEquals(jni.updateAssetManagerCalled, 1); - assertEquals(jni.dynamicFeatureInstallFailureCalled, 0); - - assertEquals(jni.searchPaths.length, 0); - assertEquals(jni.loadingUnitId, 123); - } - - @Test - public void assetManagerUpdateInvoked() throws NameNotFoundException { - TestFlutterJNI jni = new TestFlutterJNI(); - Context spyContext = spy(RuntimeEnvironment.systemContext); - doReturn(spyContext).when(spyContext).createPackageContext(any(), anyInt()); - AssetManager assetManager = spyContext.getAssets(); - String apkTestPath = "blah doesn't matter here"; - doReturn(new File(apkTestPath)).when(spyContext).getFilesDir(); - TestPlayStoreDynamicFeatureManager playStoreManager = - new TestPlayStoreDynamicFeatureManager(spyContext, jni); - jni.setDynamicFeatureManager(playStoreManager); - - assertEquals(jni.loadingUnitId, 0); - - playStoreManager.downloadDynamicFeature(123, "TestModuleName"); - assertEquals(jni.loadDartDeferredLibraryCalled, 1); - assertEquals(jni.updateAssetManagerCalled, 1); - assertEquals(jni.dynamicFeatureInstallFailureCalled, 0); - - assertEquals(jni.assetManager, assetManager); - } -} diff --git a/shell/platform/darwin/ios/framework/Source/FlutterEnginePlatformViewTest.mm b/shell/platform/darwin/ios/framework/Source/FlutterEnginePlatformViewTest.mm index fbccf6677b02f..125551a841c42 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterEnginePlatformViewTest.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterEnginePlatformViewTest.mm @@ -33,11 +33,6 @@ void OnPlatformViewSetAccessibilityFeatures(int32_t flags) override {} void OnPlatformViewRegisterTexture(std::shared_ptr texture) override {} void OnPlatformViewUnregisterTexture(int64_t texture_id) override {} void OnPlatformViewMarkTextureFrameAvailable(int64_t texture_id) override {} - - void LoadDartDeferredLibrary(intptr_t loading_unit_id, - const uint8_t* snapshot_data, - const uint8_t* snapshot_instructions) override {} - void UpdateAssetManager(std::shared_ptr asset_manager) override {} }; } // namespace diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsTest.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsTest.mm index d9abef5a093ef..0b0aa2b80da11 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsTest.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsTest.mm @@ -103,11 +103,6 @@ void OnPlatformViewSetAccessibilityFeatures(int32_t flags) override {} void OnPlatformViewRegisterTexture(std::shared_ptr texture) override {} void OnPlatformViewUnregisterTexture(int64_t texture_id) override {} void OnPlatformViewMarkTextureFrameAvailable(int64_t texture_id) override {} - - void LoadDartDeferredLibrary(intptr_t loading_unit_id, - const uint8_t* snapshot_data, - const uint8_t* snapshot_instructions) override {} - void UpdateAssetManager(std::shared_ptr asset_manager) override {} }; } // namespace diff --git a/shell/platform/darwin/ios/framework/Source/accessibility_bridge_test.mm b/shell/platform/darwin/ios/framework/Source/accessibility_bridge_test.mm index b027b20e915b4..fbb2404b7a3e2 100644 --- a/shell/platform/darwin/ios/framework/Source/accessibility_bridge_test.mm +++ b/shell/platform/darwin/ios/framework/Source/accessibility_bridge_test.mm @@ -86,11 +86,6 @@ void OnPlatformViewSetAccessibilityFeatures(int32_t flags) override {} void OnPlatformViewRegisterTexture(std::shared_ptr texture) override {} void OnPlatformViewUnregisterTexture(int64_t texture_id) override {} void OnPlatformViewMarkTextureFrameAvailable(int64_t texture_id) override {} - - void LoadDartDeferredLibrary(intptr_t loading_unit_id, - const uint8_t* snapshot_data, - const uint8_t* snapshot_instructions) override {} - void UpdateAssetManager(std::shared_ptr asset_manager) override {} }; class MockIosDelegate : public AccessibilityBridge::IosDelegate { diff --git a/shell/platform/fuchsia/flutter/platform_view_unittest.cc b/shell/platform/fuchsia/flutter/platform_view_unittest.cc index a54504a92ea74..559d2b8f7cbfb 100644 --- a/shell/platform/fuchsia/flutter/platform_view_unittest.cc +++ b/shell/platform/fuchsia/flutter/platform_view_unittest.cc @@ -104,13 +104,6 @@ class MockPlatformViewDelegate : public flutter::PlatformView::Delegate { const std::vector& supported_locale_data) { return nullptr; } - // |flutter::PlatformView::Delegate| - void LoadDartDeferredLibrary(intptr_t loading_unit_id, - const uint8_t* snapshot_data, - const uint8_t* snapshot_instructions) {} - // |flutter::PlatformView::Delegate| - void UpdateAssetManager( - std::shared_ptr asset_manager) {} flutter::Surface* surface() const { return surface_.get(); } flutter::PlatformMessage* message() const { return message_.get(); }