Skip to content

Commit

Permalink
Reapply: Android background platform channels (flutter#29346)
Browse files Browse the repository at this point in the history
* Revert "Revert "Android Background Platform Channels (flutter#29147)""

This reverts commit 7ed91e14ccc1f5ffc4cb13d1d37e27d370c8f7cd.

* Made this PR less of a breaking change by keeping setMessageHandler's signature the same
  • Loading branch information
gaaclarke authored Oct 27, 2021
1 parent 9461262 commit ac2c9af
Show file tree
Hide file tree
Showing 31 changed files with 896 additions and 167 deletions.
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 @@ -842,6 +843,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 @@ -939,6 +941,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 @@ -187,6 +189,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

0 comments on commit ac2c9af

Please sign in to comment.