Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Reapply: Android background platform channels #29346

Merged
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
4 changes: 4 additions & 0 deletions ci/licenses_golden/licenses_flutter
Original file line number Diff line number Diff line change
Expand Up @@ -708,6 +708,7 @@ FILE: ../../../flutter/shell/common/persistent_cache_unittests.cc
FILE: ../../../flutter/shell/common/pipeline.cc
FILE: ../../../flutter/shell/common/pipeline.h
FILE: ../../../flutter/shell/common/pipeline_unittests.cc
FILE: ../../../flutter/shell/common/platform_message_handler.h
FILE: ../../../flutter/shell/common/platform_view.cc
FILE: ../../../flutter/shell/common/platform_view.h
FILE: ../../../flutter/shell/common/pointer_data_dispatcher.cc
Expand Down Expand Up @@ -841,6 +842,7 @@ 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/dart/PlatformTaskQueue.java
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/deferredcomponents/DeferredComponentManager.java
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/deferredcomponents/PlayStoreDeferredComponentManager.java
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/loader/ApplicationInfoLoader.java
Expand Down Expand Up @@ -938,6 +940,8 @@ FILE: ../../../flutter/shell/platform/android/jni/jni_mock_unittest.cc
FILE: ../../../flutter/shell/platform/android/jni/platform_view_android_jni.cc
FILE: ../../../flutter/shell/platform/android/jni/platform_view_android_jni.h
FILE: ../../../flutter/shell/platform/android/library_loader.cc
FILE: ../../../flutter/shell/platform/android/platform_message_handler_android.cc
FILE: ../../../flutter/shell/platform/android/platform_message_handler_android.h
FILE: ../../../flutter/shell/platform/android/platform_message_response_android.cc
FILE: ../../../flutter/shell/platform/android/platform_message_response_android.h
FILE: ../../../flutter/shell/platform/android/platform_view_android.cc
Expand Down
1 change: 1 addition & 0 deletions shell/common/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ source_set("common") {
"engine.h",
"pipeline.cc",
"pipeline.h",
"platform_message_handler.h",
"platform_view.cc",
"platform_view.h",
"pointer_data_dispatcher.cc",
Expand Down
39 changes: 39 additions & 0 deletions shell/common/platform_message_handler.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// 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.

#ifndef SHELL_COMMON_PLATFORM_MESSAGE_HANDLER_H_
#define SHELL_COMMON_PLATFORM_MESSAGE_HANDLER_H_

#include <memory>

#include "flutter/lib/ui/window/platform_message.h"

namespace flutter {

/// An interface over the ability to handle PlatformMessages that are being sent
/// from Flutter to the host platform.
class PlatformMessageHandler {
public:
virtual ~PlatformMessageHandler() = default;

/// Ultimately sends the PlatformMessage to the host platform.
/// This method is invoked on the ui thread.
virtual void HandlePlatformMessage(
std::unique_ptr<PlatformMessage> message) = 0;

/// Performs the return procedure for an associated call to
/// HandlePlatformMessage.
/// This method should be thread-safe and able to be invoked on any thread.
virtual void InvokePlatformMessageResponseCallback(
int response_id,
std::unique_ptr<fml::Mapping> mapping) = 0;

/// Performs the return procedure for an associated call to
/// HandlePlatformMessage where there is no return value.
/// This method should be thread-safe and able to be invoked on any thread.
virtual void InvokePlatformMessageEmptyResponseCallback(int response_id) = 0;
};
} // namespace flutter

#endif // SHELL_COMMON_PLATFORM_MESSAGE_HANDLER_H_
5 changes: 5 additions & 0 deletions shell/common/platform_view.cc
Original file line number Diff line number Diff line change
Expand Up @@ -184,4 +184,9 @@ PlatformView::CreateSnapshotSurfaceProducer() {
return nullptr;
}

std::shared_ptr<PlatformMessageHandler>
PlatformView::GetPlatformMessageHandler() const {
return nullptr;
}

} // namespace flutter
12 changes: 12 additions & 0 deletions shell/common/platform_view.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "flutter/lib/ui/window/pointer_data_packet.h"
#include "flutter/lib/ui/window/pointer_data_packet_converter.h"
#include "flutter/lib/ui/window/viewport_metrics.h"
#include "flutter/shell/common/platform_message_handler.h"
#include "flutter/shell/common/pointer_data_dispatcher.h"
#include "flutter/shell/common/vsync_waiter.h"
#include "third_party/skia/include/core/SkSize.h"
Expand Down Expand Up @@ -810,6 +811,17 @@ class PlatformView {
virtual std::unique_ptr<SnapshotSurfaceProducer>
CreateSnapshotSurfaceProducer();

//--------------------------------------------------------------------------
/// @brief Specifies a delegate that will receive PlatformMessages from
/// Flutter to the host platform.
///
/// @details If this returns `null` that means PlatformMessages should be sent
/// to the PlatformView. That is to protect legacy behavior, any embedder
/// that wants to support executing Platform Channel handlers on background
/// threads should be returing a thread-safe PlatformMessageHandler instead.
virtual std::shared_ptr<PlatformMessageHandler> GetPlatformMessageHandler()
const;

protected:
PlatformView::Delegate& delegate_;
const TaskRunners task_runners_;
Expand Down
24 changes: 17 additions & 7 deletions shell/common/shell.cc
Original file line number Diff line number Diff line change
Expand Up @@ -625,6 +625,7 @@ bool Shell::Setup(std::unique_ptr<PlatformView> platform_view,
}

platform_view_ = std::move(platform_view);
platform_message_handler_ = platform_view_->GetPlatformMessageHandler();
engine_ = std::move(engine);
rasterizer_ = std::move(rasterizer);
io_manager_ = std::move(io_manager);
Expand Down Expand Up @@ -1192,13 +1193,17 @@ void Shell::OnEngineHandlePlatformMessage(
return;
}

task_runners_.GetPlatformTaskRunner()->PostTask(
fml::MakeCopyable([view = platform_view_->GetWeakPtr(),
message = std::move(message)]() mutable {
if (view) {
view->HandlePlatformMessage(std::move(message));
}
}));
if (platform_message_handler_) {
platform_message_handler_->HandlePlatformMessage(std::move(message));
} else {
task_runners_.GetPlatformTaskRunner()->PostTask(
fml::MakeCopyable([view = platform_view_->GetWeakPtr(),
message = std::move(message)]() mutable {
if (view) {
view->HandlePlatformMessage(std::move(message));
}
}));
}
}

void Shell::HandleEngineSkiaMessage(std::unique_ptr<PlatformMessage> message) {
Expand Down Expand Up @@ -1867,4 +1872,9 @@ fml::TimePoint Shell::GetCurrentTimePoint() {
return fml::TimePoint::Now();
}

const std::shared_ptr<PlatformMessageHandler>&
Shell::GetPlatformMessageHandler() const {
return platform_message_handler_;
}

} // namespace flutter
7 changes: 7 additions & 0 deletions shell/common/shell.h
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,12 @@ class Shell final : public PlatformView::Delegate,
/// @see `CreateCompatibleGenerator`
void RegisterImageDecoder(ImageGeneratorFactory factory, int32_t priority);

//----------------------------------------------------------------------------
/// @brief Returns the delegate object that handles PlatformMessage's from
/// Flutter to the host platform (and its responses).
const std::shared_ptr<PlatformMessageHandler>& GetPlatformMessageHandler()
const;

private:
using ServiceProtocolHandler =
std::function<bool(const ServiceProtocol::Handler::ServiceProtocolMap&,
Expand All @@ -412,6 +418,7 @@ class Shell final : public PlatformView::Delegate,
std::unique_ptr<ShellIOManager> io_manager_; // on IO task runner
std::shared_ptr<fml::SyncSwitch> is_gpu_disabled_sync_switch_;
std::shared_ptr<VolatilePathTracker> volatile_path_tracker_;
std::shared_ptr<PlatformMessageHandler> platform_message_handler_;

fml::WeakPtr<Engine> weak_engine_; // to be shared across threads
fml::TaskRunnerAffineWeakPtr<Rasterizer>
Expand Down
35 changes: 18 additions & 17 deletions shell/common/shell_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -325,7 +325,8 @@ std::unique_ptr<Shell> ShellTest::CreateShell(
std::shared_ptr<ShellTestExternalViewEmbedder>
shell_test_external_view_embedder,
bool is_gpu_disabled,
ShellTestPlatformView::BackendType rendering_backend) {
ShellTestPlatformView::BackendType rendering_backend,
Shell::CreateCallback<PlatformView> platform_view_create_callback) {
const auto vsync_clock = std::make_shared<ShellTestVsyncClock>();

CreateVsyncWaiter create_vsync_waiter = [&]() {
Expand All @@ -338,29 +339,29 @@ std::unique_ptr<Shell> ShellTest::CreateShell(
}
};

Shell::CreateCallback<PlatformView> platfrom_view_create_callback =
[vsync_clock, //
&create_vsync_waiter, //
shell_test_external_view_embedder, //
rendering_backend //
](Shell& shell) {
return ShellTestPlatformView::Create(
shell, //
shell.GetTaskRunners(), //
vsync_clock, //
std::move(create_vsync_waiter), //
rendering_backend, //
shell_test_external_view_embedder //
);
};
if (!platform_view_create_callback) {
platform_view_create_callback = [vsync_clock, //
&create_vsync_waiter, //
shell_test_external_view_embedder, //
rendering_backend //
](Shell& shell) {
return ShellTestPlatformView::Create(shell, //
shell.GetTaskRunners(), //
vsync_clock, //
std::move(create_vsync_waiter), //
rendering_backend, //
shell_test_external_view_embedder //
);
};
}

Shell::CreateCallback<Rasterizer> rasterizer_create_callback =
[](Shell& shell) { return std::make_unique<Rasterizer>(shell); };

return Shell::Create(flutter::PlatformData(), //
task_runners, //
settings, //
platfrom_view_create_callback, //
platform_view_create_callback, //
rasterizer_create_callback, //
is_gpu_disabled //
);
Expand Down
4 changes: 3 additions & 1 deletion shell/common/shell_test.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,9 @@ class ShellTest : public FixtureTest {
shell_test_external_view_embedder = nullptr,
bool is_gpu_disabled = false,
ShellTestPlatformView::BackendType rendering_backend =
ShellTestPlatformView::BackendType::kDefaultBackend);
ShellTestPlatformView::BackendType::kDefaultBackend,
Shell::CreateCallback<PlatformView> platform_view_create_callback =
nullptr);
void DestroyShell(std::unique_ptr<Shell> shell);
void DestroyShell(std::unique_ptr<Shell> shell, TaskRunners task_runners);
TaskRunners GetTaskRunnersForFixture();
Expand Down
70 changes: 70 additions & 0 deletions shell/common/shell_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@

namespace flutter {
namespace testing {

using ::testing::_;
using ::testing::Return;

namespace {
class MockPlatformViewDelegate : public PlatformView::Delegate {
MOCK_METHOD1(OnPlatformViewCreated, void(std::unique_ptr<Surface> surface));
Expand Down Expand Up @@ -119,6 +123,27 @@ class MockPlatformView : public PlatformView {
MockPlatformView(MockPlatformViewDelegate& delegate, TaskRunners task_runners)
: PlatformView(delegate, task_runners) {}
MOCK_METHOD0(CreateRenderingSurface, std::unique_ptr<Surface>());
MOCK_CONST_METHOD0(GetPlatformMessageHandler,
std::shared_ptr<PlatformMessageHandler>());
};

class MockPlatformMessageHandler : public PlatformMessageHandler {
public:
MOCK_METHOD1(HandlePlatformMessage,
void(std::unique_ptr<PlatformMessage> message));
MOCK_METHOD2(InvokePlatformMessageResponseCallback,
void(int response_id, std::unique_ptr<fml::Mapping> mapping));
MOCK_METHOD1(InvokePlatformMessageEmptyResponseCallback,
void(int response_id));
};

class MockPlatformMessageResponse : public PlatformMessageResponse {
public:
static fml::RefPtr<MockPlatformMessageResponse> Create() {
return fml::AdoptRef(new MockPlatformMessageResponse());
}
MOCK_METHOD1(Complete, void(std::unique_ptr<fml::Mapping> data));
MOCK_METHOD0(CompleteEmpty, void());
};
} // namespace

Expand Down Expand Up @@ -3162,7 +3187,52 @@ TEST_F(ShellTest, UIWorkAfterOnPlatformViewDestroyed) {
shell->GetTaskRunners().GetUITaskRunner(),
[&ui_flush_latch]() { ui_flush_latch.Signal(); });
ui_flush_latch.Wait();
DestroyShell(std::move(shell));
}

TEST_F(ShellTest, UsesPlatformMessageHandler) {
TaskRunners task_runners = GetTaskRunnersForFixture();
auto settings = CreateSettingsForFixture();
MockPlatformViewDelegate platform_view_delegate;
auto platform_message_handler =
std::make_shared<MockPlatformMessageHandler>();
int message_id = 1;
EXPECT_CALL(*platform_message_handler, HandlePlatformMessage(_));
EXPECT_CALL(*platform_message_handler,
InvokePlatformMessageEmptyResponseCallback(message_id));
Shell::CreateCallback<PlatformView> platform_view_create_callback =
[&platform_view_delegate, task_runners,
platform_message_handler](flutter::Shell& shell) {
auto result = std::make_unique<MockPlatformView>(platform_view_delegate,
task_runners);
EXPECT_CALL(*result, GetPlatformMessageHandler())
.WillOnce(Return(platform_message_handler));
return result;
};
auto shell = CreateShell(
/*settings=*/std::move(settings),
/*task_runners=*/task_runners,
/*simulate_vsync=*/false,
/*shell_test_external_view_embedder=*/nullptr,
/*is_gpu_disabled=*/false,
/*rendering_backend=*/
ShellTestPlatformView::BackendType::kDefaultBackend,
/*platform_view_create_callback=*/platform_view_create_callback);

EXPECT_EQ(platform_message_handler, shell->GetPlatformMessageHandler());
PostSync(task_runners.GetUITaskRunner(), [&shell]() {
size_t data_size = 4;
fml::MallocMapping bytes =
fml::MallocMapping(static_cast<uint8_t*>(malloc(data_size)), data_size);
fml::RefPtr<MockPlatformMessageResponse> response =
MockPlatformMessageResponse::Create();
auto message = std::make_unique<PlatformMessage>(
/*channel=*/"foo", /*data=*/std::move(bytes), /*response=*/response);
(static_cast<Engine::Delegate*>(shell.get()))
->OnEngineHandlePlatformMessage(std::move(message));
});
shell->GetPlatformMessageHandler()
->InvokePlatformMessageEmptyResponseCallback(message_id);
DestroyShell(std::move(shell));
}

Expand Down
3 changes: 3 additions & 0 deletions shell/platform/android/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ source_set("flutter_shell_native_src") {
"flutter_main.cc",
"flutter_main.h",
"library_loader.cc",
"platform_message_handler_android.cc",
"platform_message_handler_android.h",
"platform_message_response_android.cc",
"platform_message_response_android.h",
"platform_view_android.cc",
Expand Down Expand Up @@ -186,6 +188,7 @@ 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/dart/PlatformTaskQueue.java",
"io/flutter/embedding/engine/deferredcomponents/DeferredComponentManager.java",
"io/flutter/embedding/engine/deferredcomponents/PlayStoreDeferredComponentManager.java",
"io/flutter/embedding/engine/loader/ApplicationInfoLoader.java",
Expand Down
6 changes: 6 additions & 0 deletions shell/platform/android/android_shell_holder.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "flutter/shell/common/shell.h"
#include "flutter/shell/common/thread_host.h"
#include "flutter/shell/platform/android/jni/platform_view_android_jni.h"
#include "flutter/shell/platform/android/platform_message_handler_android.h"
#include "flutter/shell/platform/android/platform_view_android.h"

namespace flutter {
Expand Down Expand Up @@ -96,6 +97,11 @@ class AndroidShellHolder {

void NotifyLowMemoryWarning();

const std::shared_ptr<PlatformMessageHandler>& GetPlatformMessageHandler()
const {
return shell_->GetPlatformMessageHandler();
}

private:
const flutter::Settings settings_;
const std::shared_ptr<PlatformViewAndroidJNI> jni_facade_;
Expand Down
Loading