Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions .ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -88,11 +88,15 @@ targets:
- name: Linux linux_android_emulator_tests
enabled_branches:
- main
recipe: engine_v2/builder
presubmit: false
recipe: engine_v2/engine_v2
bringup: true
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This needs some time for the engine_v2 selection to propagate, per @godofredoc

properties:
config_name: linux_android_emulator
timeout: 60
runIf:
- .ci.yaml
- lib/ui/**
- shell/platform/android/**

- name: Linux builder_cache
enabled_branches:
Expand Down
111 changes: 111 additions & 0 deletions ci/builders/linux_android_emulator.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
{
"builds": [
{
"drone_dimensions": [
"device_type=none",
"os=Linux",
"kvm=1",
"cores=8"
],
"gn": [
"--android",
"--android-cpu=x64",
"--no-lto",
"--rbe",
"--no-goma"
],
"name": "android_debug_x64",
"ninja": {
"config": "android_debug_x64",
"targets": [
"flutter/shell/platform/android:flutter_shell_native_unittests",
"flutter/testing/scenario_app"
]
},
"tests": [
{
"language": "python3",
"name": "Android Unit Tests",
"test_dependencies": [
{
"dependency": "android_virtual_device",
"version": "34"
}
],
"contexts": [
"android_virtual_device"
],
"script": "flutter/testing/run_tests.py",
"parameters": [
"--android-variant",
"android_debug_x64",
"--type",
"android"
]
},
{
"language": "bash",
"name": "Scenario App Integration Tests",
"test_dependencies": [
{
"dependency": "android_virtual_device",
"version": "34"
}
],
"contexts": [
"android_virtual_device"
],
"script": "flutter/testing/scenario_app/run_android_tests.sh",
"parameters": [
"android_debug_x64"
]
}
]
},
{
"drone_dimensions": [
"device_type=none",
"os=Linux",
"kvm=1",
"cores=8"
],
"gn": [
"--android",
"--android-cpu=x86",
"--no-lto",
"--rbe",
"--no-goma"
],
"name": "android_debug_x86",
"ninja": {
"config": "android_debug_x86",
"targets": [
"flutter/shell/platform/android:flutter_shell_native_unittests",
"flutter/testing/scenario_app"
]
},
"tests": [
{
"language": "python3",
"name": "Android Unit Tests (API 28)",
"test_dependencies": [
{
"dependency": "android_virtual_device",
"version": "28"
}
],
"contexts": [
"android_virtual_device"
],
"script": "flutter/testing/run_tests.py",
"parameters": [
"--android-variant",
"android_debug_x86",
"--type",
"android"
]
}
]
}
]
}
60 changes: 0 additions & 60 deletions ci/builders/standalone/linux_android_emulator.json

This file was deleted.

1 change: 1 addition & 0 deletions ci/licenses_golden/excluded_files
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,7 @@
../../../flutter/shell/platform/android/flutter_shell_native_unittests.cc
../../../flutter/shell/platform/android/jni/jni_mock_unittest.cc
../../../flutter/shell/platform/android/platform_view_android_delegate/platform_view_android_delegate_unittests.cc
../../../flutter/shell/platform/android/platform_view_android_unittests.cc
../../../flutter/shell/platform/android/test
../../../flutter/shell/platform/android/test_runner
../../../flutter/shell/platform/common/accessibility_bridge_unittests.cc
Expand Down
1 change: 1 addition & 0 deletions shell/platform/android/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ executable("flutter_shell_native_unittests") {
"android_shell_holder_unittests.cc",
"apk_asset_provider_unittests.cc",
"flutter_shell_native_unittests.cc",
"platform_view_android_unittests.cc",
]
public_configs = [ "//flutter:config" ]
deps = [
Expand Down
24 changes: 24 additions & 0 deletions shell/platform/android/platform_view_android.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#include "flutter/shell/platform/android/platform_view_android.h"

#include <android/api-level.h>
#include <memory>
#include <utility>

Expand Down Expand Up @@ -33,6 +34,8 @@

namespace flutter {

constexpr int kMinimumAndroidApiLevelForVulkan = 29;

AndroidSurfaceFactoryImpl::AndroidSurfaceFactoryImpl(
const std::shared_ptr<AndroidContext>& context,
bool enable_impeller)
Expand Down Expand Up @@ -73,9 +76,30 @@ static std::shared_ptr<flutter::AndroidContext> CreateAndroidContext(
bool enable_vulkan_validation,
bool enable_opengl_gpu_tracing) {
if (use_software_rendering) {
FML_DCHECK(!enable_impeller);
return std::make_shared<AndroidContext>(AndroidRenderingAPI::kSoftware);
}
if (enable_impeller) {
// Vulkan must only be used on API level 29+, as older API levels do not
// have requisite features to support platform views.
//
// 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) {
if (impeller_backend.value_or("") == "vulkan") {
FML_LOG(WARNING)
<< "Impeller Vulkan requested, but detected Android API level "
<< api_level
<< " does not support required features for Vulkan with platform "
"views. Falling back to OpenGLES.";
}
return std::make_unique<AndroidContextGLImpeller>(
std::make_unique<impeller::egl::Display>(),
enable_opengl_gpu_tracing);
}

// Default value is Vulkan with GLES fallback.
AndroidRenderingAPI backend = AndroidRenderingAPI::kAutoselect;
if (impeller_backend.has_value()) {
Expand Down
133 changes: 133 additions & 0 deletions shell/platform/android/platform_view_android_unittests.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
// 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.

#include "flutter/shell/platform/android/platform_view_android.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "shell/platform/android/context/android_context.h"
#include "third_party/googletest/googlemock/include/gmock/gmock-nice-strict.h"

namespace flutter {
namespace testing {

using ::testing::NiceMock;
using ::testing::ReturnRef;

namespace {
class MockPlatformViewDelegate : public PlatformView::Delegate {
public:
MOCK_METHOD(void,
OnPlatformViewCreated,
(std::unique_ptr<Surface> surface),
(override));

MOCK_METHOD(void, OnPlatformViewDestroyed, (), (override));

MOCK_METHOD(void, OnPlatformViewScheduleFrame, (), (override));

MOCK_METHOD(void,
OnPlatformViewSetNextFrameCallback,
(const fml::closure& closure),
(override));

MOCK_METHOD(void,
OnPlatformViewSetViewportMetrics,
(int64_t view_id, const ViewportMetrics& metrics),
(override));

MOCK_METHOD(void,
OnPlatformViewDispatchPlatformMessage,
(std::unique_ptr<PlatformMessage> message),
(override));

MOCK_METHOD(void,
OnPlatformViewDispatchPointerDataPacket,
(std::unique_ptr<PointerDataPacket> packet),
(override));

MOCK_METHOD(void,
OnPlatformViewDispatchSemanticsAction,
(int32_t id, SemanticsAction action, fml::MallocMapping args),
(override));

MOCK_METHOD(void,
OnPlatformViewSetSemanticsEnabled,
(bool enabled),
(override));

MOCK_METHOD(void,
OnPlatformViewSetAccessibilityFeatures,
(int32_t flags),
(override));

MOCK_METHOD(void,
OnPlatformViewRegisterTexture,
(std::shared_ptr<Texture> texture),
(override));

MOCK_METHOD(void,
OnPlatformViewUnregisterTexture,
(int64_t texture_id),
(override));

MOCK_METHOD(void,
OnPlatformViewMarkTextureFrameAvailable,
(int64_t texture_id),
(override));

MOCK_METHOD(const Settings&,
OnPlatformViewGetSettings,
(),
(const, override));

MOCK_METHOD(void,
LoadDartDeferredLibrary,
(intptr_t loading_unit_id,
std::unique_ptr<const fml::Mapping> snapshot_data,
std::unique_ptr<const fml::Mapping> snapshot_instructions),
(override));

MOCK_METHOD(void,
LoadDartDeferredLibraryError,
(intptr_t loading_unit_id,
const std::string error_message,
bool transient),
(override));

MOCK_METHOD(void,
UpdateAssetResolverByType,
(std::unique_ptr<AssetResolver> updated_asset_resolver,
AssetResolver::AssetResolverType type),
(override));
};
} // namespace

TEST(AndroidPlatformView, SelectsVulkanBasedOnApiLevel) {
Settings settings;
settings.enable_software_rendering = false;
settings.enable_impeller = true;
settings.impeller_backend = "vulkan";
NiceMock<MockPlatformViewDelegate> mock_delegate;
EXPECT_CALL(mock_delegate, OnPlatformViewGetSettings)
.WillRepeatedly(ReturnRef(settings));

TaskRunners task_runners("test", nullptr, nullptr, nullptr, nullptr);
PlatformViewAndroid platform_view(/*delegate=*/mock_delegate,
/*task_runners=*/task_runners,
/*jni_facade=*/nullptr,
/*use_software_rendering=*/false,
/*msaa_samples=*/1);
auto context = platform_view.GetAndroidContext();
EXPECT_TRUE(context);
int api_level = android_get_device_api_level();
EXPECT_GT(api_level, 0);
if (api_level >= 29) {
EXPECT_TRUE(context->RenderingApi() == AndroidRenderingAPI::kVulkan);
} else {
EXPECT_TRUE(context->RenderingApi() == AndroidRenderingAPI::kOpenGLES);
}
}

} // namespace testing
} // namespace flutter