Clone the parent Android engine's asset provider into a spawned engine (flutter/engine#41642)

Typically the AndroidShellHolder's apk_asset_provider_ is set by AndroidShellHolder::Launch when the DartExecutor runs the engine's entrypoint.

But if the engine was started by Spawn, then the apk_asset_provider_ was not being set.  This would cause a crash if the resulting engine was later used to spawn another engine.

Fixes https://github.com/flutter/flutter/issues/122364
This commit is contained in:
Jason Simmons
2023-05-02 07:50:58 -07:00
committed by GitHub
parent 3852c65b74
commit 5e4cd80437
6 changed files with 88 additions and 4 deletions

View File

@@ -180,12 +180,14 @@ AndroidShellHolder::AndroidShellHolder(
const std::shared_ptr<PlatformViewAndroidJNI>& jni_facade,
const std::shared_ptr<ThreadHost>& thread_host,
std::unique_ptr<Shell> shell,
std::unique_ptr<APKAssetProvider> apk_asset_provider,
const fml::WeakPtr<PlatformViewAndroid>& platform_view)
: settings_(settings),
jni_facade_(jni_facade),
platform_view_(platform_view),
thread_host_(thread_host),
shell_(std::move(shell)) {
shell_(std::move(shell)),
apk_asset_provider_(std::move(apk_asset_provider)) {
FML_DCHECK(jni_facade);
FML_DCHECK(shell_);
FML_DCHECK(shell_->IsSetup());
@@ -270,9 +272,9 @@ std::unique_ptr<AndroidShellHolder> AndroidShellHolder::Spawn(
shell_->Spawn(std::move(config.value()), initial_route,
on_create_platform_view, on_create_rasterizer);
return std::unique_ptr<AndroidShellHolder>(
new AndroidShellHolder(GetSettings(), jni_facade, thread_host_,
std::move(shell), weak_platform_view));
return std::unique_ptr<AndroidShellHolder>(new AndroidShellHolder(
GetSettings(), jni_facade, thread_host_, std::move(shell),
apk_asset_provider_->Clone(), weak_platform_view));
}
void AndroidShellHolder::Launch(

View File

@@ -128,6 +128,7 @@ class AndroidShellHolder {
const std::shared_ptr<PlatformViewAndroidJNI>& jni_facade,
const std::shared_ptr<ThreadHost>& thread_host,
std::unique_ptr<Shell> shell,
std::unique_ptr<APKAssetProvider> apk_asset_provider,
const fml::WeakPtr<PlatformViewAndroid>& platform_view);
static void ThreadDestructCallback(void* value);
std::optional<RunConfiguration> BuildRunConfiguration(

View File

@@ -21,9 +21,11 @@ _android_sources = [
"app/src/androidTest/java/dev/flutter/scenariosui/PlatformViewWithTextureViewUiTest.java",
"app/src/androidTest/java/dev/flutter/scenariosui/ScreenshotUtil.java",
"app/src/androidTest/java/dev/flutter/scenariosui/SpawnEngineTests.java",
"app/src/androidTest/java/dev/flutter/scenariosui/SpawnMultiEngineTest.java",
"app/src/main/AndroidManifest.xml",
"app/src/main/java/dev/flutter/scenarios/GetBitmapActivity.java",
"app/src/main/java/dev/flutter/scenarios/PlatformViewsActivity.java",
"app/src/main/java/dev/flutter/scenarios/SpawnMultiEngineActivity.java",
"app/src/main/java/dev/flutter/scenarios/SpawnedEngineActivity.java",
"app/src/main/java/dev/flutter/scenarios/StrictModeFlutterActivity.java",
"app/src/main/java/dev/flutter/scenarios/SurfacePlatformViewFactory.java",

View File

@@ -0,0 +1,37 @@
// 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 dev.flutter.scenariosui;
import android.content.Intent;
import androidx.annotation.NonNull;
import androidx.test.filters.LargeTest;
import androidx.test.rule.ActivityTestRule;
import androidx.test.runner.AndroidJUnit4;
import dev.flutter.scenarios.SpawnMultiEngineActivity;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(AndroidJUnit4.class)
@LargeTest
public class SpawnMultiEngineTest {
Intent intent;
@Rule @NonNull
public ActivityTestRule<SpawnMultiEngineActivity> activityRule =
new ActivityTestRule<>(
SpawnMultiEngineActivity.class, /*initialTouchMode=*/ false, /*launchActivity=*/ false);
@Before
public void setUp() {
intent = new Intent(Intent.ACTION_MAIN);
}
@Test
public void testSpawnedEngine() throws Exception {
activityRule.launchActivity(intent);
}
}

View File

@@ -37,6 +37,18 @@
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".SpawnMultiEngineActivity"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:launchMode="singleTop"
android:windowSoftInputMode="adjustResize"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".ExternalTextureFlutterActivity"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"

View File

@@ -0,0 +1,30 @@
// 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 dev.flutter.scenarios;
import android.content.Context;
import androidx.annotation.NonNull;
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.embedding.engine.FlutterEngineGroup;
public class SpawnMultiEngineActivity extends TestActivity {
static final String TAG = "Scenarios";
@Override
@NonNull
public FlutterEngine provideFlutterEngine(@NonNull Context context) {
FlutterEngineGroup engineGroup = new FlutterEngineGroup(context);
FlutterEngine firstEngine = engineGroup.createAndRunDefaultEngine(context);
FlutterEngine secondEngine = engineGroup.createAndRunDefaultEngine(context);
// Check that a new engine can be spawned from the group even if the group's
// original engine has been destroyed.
firstEngine.destroy();
FlutterEngine thirdEngine = engineGroup.createAndRunDefaultEngine(context);
return thirdEngine;
}
}