[Android] Use java for looking up Android API level. (#163558)
android_get_device_api_level is an API 24 API, whereas flutter supports down to API 21. We have other places in the engine that use this API but they're not on paths that work < 29. Even though the ndk API seems to work on older devices we should still probably not rely on it...
This commit is contained in:
parent
6f71aa9901
commit
cd7a24c1b9
@ -95,7 +95,8 @@ void FlutterMain::Init(JNIEnv* env,
|
||||
jstring kernelPath,
|
||||
jstring appStoragePath,
|
||||
jstring engineCachesPath,
|
||||
jlong initTimeMillis) {
|
||||
jlong initTimeMillis,
|
||||
jint api_level) {
|
||||
std::vector<std::string> args;
|
||||
args.push_back("flutter");
|
||||
for (auto& arg : fml::jni::StringArrayToVector(env, jargs)) {
|
||||
@ -118,8 +119,12 @@ void FlutterMain::Init(JNIEnv* env,
|
||||
"Dart DevTools.");
|
||||
}
|
||||
}
|
||||
// The API level must be provided from java, as the NDK function
|
||||
// android_get_device_api_level() is only available on API 24 and greater, and
|
||||
// Flutter still supports 21, 22, and 23.
|
||||
|
||||
AndroidRenderingAPI android_rendering_api = SelectedRenderingAPI(settings);
|
||||
AndroidRenderingAPI android_rendering_api =
|
||||
SelectedRenderingAPI(settings, api_level);
|
||||
switch (android_rendering_api) {
|
||||
case AndroidRenderingAPI::kSoftware:
|
||||
case AndroidRenderingAPI::kSkiaOpenGLES:
|
||||
@ -233,7 +238,7 @@ bool FlutterMain::Register(JNIEnv* env) {
|
||||
{
|
||||
.name = "nativeInit",
|
||||
.signature = "(Landroid/content/Context;[Ljava/lang/String;Ljava/"
|
||||
"lang/String;Ljava/lang/String;Ljava/lang/String;J)V",
|
||||
"lang/String;Ljava/lang/String;Ljava/lang/String;JI)V",
|
||||
.fnPtr = reinterpret_cast<void*>(&Init),
|
||||
},
|
||||
{
|
||||
@ -271,7 +276,8 @@ bool FlutterMain::IsKnownBadSOC(std::string_view hardware) {
|
||||
|
||||
// static
|
||||
AndroidRenderingAPI FlutterMain::SelectedRenderingAPI(
|
||||
const flutter::Settings& settings) {
|
||||
const flutter::Settings& settings,
|
||||
int api_level) {
|
||||
if (settings.enable_software_rendering) {
|
||||
FML_CHECK(!settings.enable_impeller)
|
||||
<< "Impeller does not support software rendering. Either disable "
|
||||
@ -301,7 +307,6 @@ AndroidRenderingAPI FlutterMain::SelectedRenderingAPI(
|
||||
// Even if this check returns true, Impeller may determine it cannot use
|
||||
// Vulkan for some other reason, such as a missing required extension or
|
||||
// feature.
|
||||
int api_level = android_get_device_api_level();
|
||||
if (api_level < kMinimumAndroidApiLevelForVulkan) {
|
||||
return kVulkanUnsupportedFallback;
|
||||
}
|
||||
|
@ -26,7 +26,8 @@ class FlutterMain {
|
||||
flutter::AndroidRenderingAPI GetAndroidRenderingAPI();
|
||||
|
||||
static AndroidRenderingAPI SelectedRenderingAPI(
|
||||
const flutter::Settings& settings);
|
||||
const flutter::Settings& settings,
|
||||
int api_level);
|
||||
|
||||
static bool IsDeviceEmulator(std::string_view product_model);
|
||||
|
||||
@ -47,7 +48,8 @@ class FlutterMain {
|
||||
jstring kernelPath,
|
||||
jstring appStoragePath,
|
||||
jstring engineCachesPath,
|
||||
jlong initTimeMillis);
|
||||
jlong initTimeMillis,
|
||||
jint api_level);
|
||||
|
||||
void SetupDartVMServiceUriCallback(JNIEnv* env);
|
||||
|
||||
|
@ -180,7 +180,8 @@ public class FlutterJNI {
|
||||
@Nullable String bundlePath,
|
||||
@NonNull String appStoragePath,
|
||||
@NonNull String engineCachesPath,
|
||||
long initTimeMillis);
|
||||
long initTimeMillis,
|
||||
int apiLevel);
|
||||
|
||||
/**
|
||||
* Perform one time initialization of the Dart VM and Flutter engine.
|
||||
@ -193,6 +194,7 @@ public class FlutterJNI {
|
||||
* @param appStoragePath The path to the application data directory.
|
||||
* @param engineCachesPath The path to the application cache directory.
|
||||
* @param initTimeMillis The time, in milliseconds, taken for initialization.
|
||||
* @param apiLevel The current Android API level.
|
||||
*/
|
||||
public void init(
|
||||
@NonNull Context context,
|
||||
@ -200,13 +202,14 @@ public class FlutterJNI {
|
||||
@Nullable String bundlePath,
|
||||
@NonNull String appStoragePath,
|
||||
@NonNull String engineCachesPath,
|
||||
long initTimeMillis) {
|
||||
long initTimeMillis,
|
||||
int apiLevel) {
|
||||
if (FlutterJNI.initCalled) {
|
||||
Log.w(TAG, "FlutterJNI.init called more than once");
|
||||
}
|
||||
|
||||
FlutterJNI.nativeInit(
|
||||
context, args, bundlePath, appStoragePath, engineCachesPath, initTimeMillis);
|
||||
context, args, bundlePath, appStoragePath, engineCachesPath, initTimeMillis, apiLevel);
|
||||
FlutterJNI.initCalled = true;
|
||||
}
|
||||
|
||||
@ -247,7 +250,7 @@ public class FlutterJNI {
|
||||
* VM Service URI for the VM instance.
|
||||
*
|
||||
* <p>Its value is set by the native engine once {@link #init(Context, String[], String, String,
|
||||
* String, long)} is run.
|
||||
* String, long, int)} is run.
|
||||
*/
|
||||
@Nullable
|
||||
public static String getVMServiceUri() {
|
||||
@ -258,7 +261,7 @@ public class FlutterJNI {
|
||||
* VM Service URI for the VM instance.
|
||||
*
|
||||
* <p>Its value is set by the native engine once {@link #init(Context, String[], String, String,
|
||||
* String, long)} is run.
|
||||
* String, long, int)} is run.
|
||||
*
|
||||
* @deprecated replaced by {@link #getVMServiceUri()}.
|
||||
*/
|
||||
@ -448,7 +451,8 @@ public class FlutterJNI {
|
||||
* #attachToNative()}.
|
||||
*
|
||||
* <p>Static methods that should be only called once such as {@link #init(Context, String[],
|
||||
* String, String, String, long)} shouldn't be called again on the spawned FlutterJNI instance.
|
||||
* String, String, String, long, int)} shouldn't be called again on the spawned FlutterJNI
|
||||
* instance.
|
||||
*/
|
||||
@UiThread
|
||||
@NonNull
|
||||
|
@ -390,7 +390,8 @@ public class FlutterLoader {
|
||||
kernelPath,
|
||||
result.appStoragePath,
|
||||
result.engineCachesPath,
|
||||
initTimeMillis);
|
||||
initTimeMillis,
|
||||
Integer.valueOf(android.os.Build.VERSION.SDK_INT));
|
||||
|
||||
initialized = true;
|
||||
} catch (Exception e) {
|
||||
|
@ -21,15 +21,10 @@ TEST(AndroidPlatformView, DISABLED_SelectsVulkanBasedOnApiLevel) {
|
||||
settings.enable_software_rendering = false;
|
||||
settings.enable_impeller = true;
|
||||
|
||||
int api_level = android_get_device_api_level();
|
||||
EXPECT_GT(api_level, 0);
|
||||
if (api_level >= 29) {
|
||||
EXPECT_EQ(FlutterMain::SelectedRenderingAPI(settings),
|
||||
AndroidRenderingAPI::kImpellerVulkan);
|
||||
} else {
|
||||
EXPECT_EQ(FlutterMain::SelectedRenderingAPI(settings),
|
||||
AndroidRenderingAPI::kImpellerOpenGLES);
|
||||
}
|
||||
EXPECT_EQ(FlutterMain::SelectedRenderingAPI(settings, 29),
|
||||
AndroidRenderingAPI::kImpellerVulkan);
|
||||
EXPECT_EQ(FlutterMain::SelectedRenderingAPI(settings, 24),
|
||||
AndroidRenderingAPI::kImpellerOpenGLES);
|
||||
}
|
||||
|
||||
TEST(AndroidPlatformView, SoftwareRenderingNotSupportedWithImpeller) {
|
||||
@ -37,7 +32,7 @@ TEST(AndroidPlatformView, SoftwareRenderingNotSupportedWithImpeller) {
|
||||
settings.enable_software_rendering = true;
|
||||
settings.enable_impeller = true;
|
||||
|
||||
ASSERT_DEATH(FlutterMain::SelectedRenderingAPI(settings), "");
|
||||
ASSERT_DEATH(FlutterMain::SelectedRenderingAPI(settings, 29), "");
|
||||
}
|
||||
|
||||
TEST(AndroidPlatformView, FallsBackToGLESonEmulator) {
|
||||
|
@ -9,6 +9,7 @@ import static io.flutter.Build.API_LEVELS;
|
||||
import static junit.framework.TestCase.assertFalse;
|
||||
import static junit.framework.TestCase.assertTrue;
|
||||
import static org.mockito.Mockito.any;
|
||||
import static org.mockito.Mockito.anyInt;
|
||||
import static org.mockito.Mockito.anyLong;
|
||||
import static org.mockito.Mockito.anyString;
|
||||
import static org.mockito.Mockito.eq;
|
||||
@ -99,7 +100,14 @@ public class FlutterLoaderTest {
|
||||
final String oldGenHeapArg = "--old-gen-heap-size=" + oldGenHeapSizeMegaBytes;
|
||||
ArgumentCaptor<String[]> shellArgsCaptor = ArgumentCaptor.forClass(String[].class);
|
||||
verify(mockFlutterJNI, times(1))
|
||||
.init(eq(ctx), shellArgsCaptor.capture(), anyString(), anyString(), anyString(), anyLong());
|
||||
.init(
|
||||
eq(ctx),
|
||||
shellArgsCaptor.capture(),
|
||||
anyString(),
|
||||
anyString(),
|
||||
anyString(),
|
||||
anyLong(),
|
||||
anyInt());
|
||||
List<String> arguments = Arrays.asList(shellArgsCaptor.getValue());
|
||||
assertTrue(arguments.contains(oldGenHeapArg));
|
||||
}
|
||||
@ -122,7 +130,14 @@ public class FlutterLoaderTest {
|
||||
"--resource-cache-max-bytes-threshold=" + resourceCacheMaxBytesThreshold;
|
||||
ArgumentCaptor<String[]> shellArgsCaptor = ArgumentCaptor.forClass(String[].class);
|
||||
verify(mockFlutterJNI, times(1))
|
||||
.init(eq(ctx), shellArgsCaptor.capture(), anyString(), anyString(), anyString(), anyLong());
|
||||
.init(
|
||||
eq(ctx),
|
||||
shellArgsCaptor.capture(),
|
||||
anyString(),
|
||||
anyString(),
|
||||
anyString(),
|
||||
anyLong(),
|
||||
anyInt());
|
||||
List<String> arguments = Arrays.asList(shellArgsCaptor.getValue());
|
||||
assertTrue(arguments.contains(resourceCacheMaxBytesThresholdArg));
|
||||
}
|
||||
@ -140,7 +155,14 @@ public class FlutterLoaderTest {
|
||||
final String leakVMArg = "--leak-vm=true";
|
||||
ArgumentCaptor<String[]> shellArgsCaptor = ArgumentCaptor.forClass(String[].class);
|
||||
verify(mockFlutterJNI, times(1))
|
||||
.init(eq(ctx), shellArgsCaptor.capture(), anyString(), anyString(), anyString(), anyLong());
|
||||
.init(
|
||||
eq(ctx),
|
||||
shellArgsCaptor.capture(),
|
||||
anyString(),
|
||||
anyString(),
|
||||
anyString(),
|
||||
anyLong(),
|
||||
anyInt());
|
||||
List<String> arguments = Arrays.asList(shellArgsCaptor.getValue());
|
||||
assertTrue(arguments.contains(leakVMArg));
|
||||
}
|
||||
@ -162,7 +184,14 @@ public class FlutterLoaderTest {
|
||||
final String leakVMArg = "--leak-vm=false";
|
||||
ArgumentCaptor<String[]> shellArgsCaptor = ArgumentCaptor.forClass(String[].class);
|
||||
verify(mockFlutterJNI, times(1))
|
||||
.init(eq(ctx), shellArgsCaptor.capture(), anyString(), anyString(), anyString(), anyLong());
|
||||
.init(
|
||||
eq(ctx),
|
||||
shellArgsCaptor.capture(),
|
||||
anyString(),
|
||||
anyString(),
|
||||
anyString(),
|
||||
anyLong(),
|
||||
anyInt());
|
||||
List<String> arguments = Arrays.asList(shellArgsCaptor.getValue());
|
||||
assertTrue(arguments.contains(leakVMArg));
|
||||
}
|
||||
@ -191,7 +220,14 @@ public class FlutterLoaderTest {
|
||||
final String enableImpellerArg = "--enable-impeller";
|
||||
ArgumentCaptor<String[]> shellArgsCaptor = ArgumentCaptor.forClass(String[].class);
|
||||
verify(mockFlutterJNI, times(1))
|
||||
.init(eq(ctx), shellArgsCaptor.capture(), anyString(), anyString(), anyString(), anyLong());
|
||||
.init(
|
||||
eq(ctx),
|
||||
shellArgsCaptor.capture(),
|
||||
anyString(),
|
||||
anyString(),
|
||||
anyString(),
|
||||
anyLong(),
|
||||
anyInt());
|
||||
List<String> arguments = Arrays.asList(shellArgsCaptor.getValue());
|
||||
assertFalse(arguments.contains(enableImpellerArg));
|
||||
}
|
||||
@ -209,7 +245,14 @@ public class FlutterLoaderTest {
|
||||
final String enableVulkanValidationArg = "--enable-vulkan-validation";
|
||||
ArgumentCaptor<String[]> shellArgsCaptor = ArgumentCaptor.forClass(String[].class);
|
||||
verify(mockFlutterJNI, times(1))
|
||||
.init(eq(ctx), shellArgsCaptor.capture(), anyString(), anyString(), anyString(), anyLong());
|
||||
.init(
|
||||
eq(ctx),
|
||||
shellArgsCaptor.capture(),
|
||||
anyString(),
|
||||
anyString(),
|
||||
anyString(),
|
||||
anyLong(),
|
||||
anyInt());
|
||||
List<String> arguments = Arrays.asList(shellArgsCaptor.getValue());
|
||||
assertFalse(arguments.contains(enableVulkanValidationArg));
|
||||
}
|
||||
@ -231,7 +274,14 @@ public class FlutterLoaderTest {
|
||||
final String enableImpellerArg = "--enable-impeller=true";
|
||||
ArgumentCaptor<String[]> shellArgsCaptor = ArgumentCaptor.forClass(String[].class);
|
||||
verify(mockFlutterJNI, times(1))
|
||||
.init(eq(ctx), shellArgsCaptor.capture(), anyString(), anyString(), anyString(), anyLong());
|
||||
.init(
|
||||
eq(ctx),
|
||||
shellArgsCaptor.capture(),
|
||||
anyString(),
|
||||
anyString(),
|
||||
anyString(),
|
||||
anyLong(),
|
||||
anyInt());
|
||||
List<String> arguments = Arrays.asList(shellArgsCaptor.getValue());
|
||||
assertTrue(arguments.contains(enableImpellerArg));
|
||||
}
|
||||
@ -253,7 +303,14 @@ public class FlutterLoaderTest {
|
||||
final String disabledControlArg = "--enable-surface-control";
|
||||
ArgumentCaptor<String[]> shellArgsCaptor = ArgumentCaptor.forClass(String[].class);
|
||||
verify(mockFlutterJNI, times(1))
|
||||
.init(eq(ctx), shellArgsCaptor.capture(), anyString(), anyString(), anyString(), anyLong());
|
||||
.init(
|
||||
eq(ctx),
|
||||
shellArgsCaptor.capture(),
|
||||
anyString(),
|
||||
anyString(),
|
||||
anyString(),
|
||||
anyLong(),
|
||||
anyInt());
|
||||
List<String> arguments = Arrays.asList(shellArgsCaptor.getValue());
|
||||
assertTrue(arguments.contains(disabledControlArg));
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user