提交 dec24015 编写于 作者: A Adam Barth 提交者: GitHub

Add new platform message transport on Android (#3105)

This transport uses the Dart and JNI APIs directly instead of indirecting
through Mojo.
上级 881fc584
......@@ -15,10 +15,14 @@ Threads* g_threads = nullptr;
Threads::Threads() {}
Threads::Threads(ftl::RefPtr<ftl::TaskRunner> gpu,
Threads::Threads(ftl::RefPtr<ftl::TaskRunner> platform,
ftl::RefPtr<ftl::TaskRunner> gpu,
ftl::RefPtr<ftl::TaskRunner> ui,
ftl::RefPtr<ftl::TaskRunner> io)
: gpu_(std::move(gpu)), ui_(std::move(ui)), io_(std::move(io)) {}
: platform_(std::move(platform)),
gpu_(std::move(gpu)),
ui_(std::move(ui)),
io_(std::move(io)) {}
Threads::~Threads() {}
......
......@@ -12,11 +12,13 @@ namespace blink {
class Threads {
public:
Threads();
Threads(ftl::RefPtr<ftl::TaskRunner> gpu,
Threads(ftl::RefPtr<ftl::TaskRunner> platform,
ftl::RefPtr<ftl::TaskRunner> gpu,
ftl::RefPtr<ftl::TaskRunner> ui,
ftl::RefPtr<ftl::TaskRunner> io);
~Threads();
static const ftl::RefPtr<ftl::TaskRunner>& Platform();
static const ftl::RefPtr<ftl::TaskRunner>& Gpu();
static const ftl::RefPtr<ftl::TaskRunner>& UI();
static const ftl::RefPtr<ftl::TaskRunner>& IO();
......@@ -26,6 +28,7 @@ class Threads {
private:
static const Threads& Get();
ftl::RefPtr<ftl::TaskRunner> platform_;
ftl::RefPtr<ftl::TaskRunner> gpu_;
ftl::RefPtr<ftl::TaskRunner> ui_;
ftl::RefPtr<ftl::TaskRunner> io_;
......
......@@ -51,8 +51,9 @@ class App : public mojo::ApplicationImplBase {
ftl::RefPtr<ftl::TaskRunner> io_task_runner;
io_thread_ = mtl::CreateThread(&io_task_runner);
blink::Threads::Set(
blink::Threads(gpu_task_runner, ui_task_runner, io_task_runner));
// Notice that the Platform and UI threads are actually the same.
blink::Threads::Set(blink::Threads(ui_task_runner, gpu_task_runner,
ui_task_runner, io_task_runner));
blink::Settings::Set(blink::Settings());
blink::InitRuntime();
......
......@@ -18,14 +18,14 @@ source_set("ui") {
"painting/canvas.h",
"painting/gradient.cc",
"painting/gradient.h",
"painting/image.cc",
"painting/image.h",
"painting/image_decoding.cc",
"painting/image_decoding.h",
"painting/image_filter.cc",
"painting/image_filter.h",
"painting/image_shader.cc",
"painting/image_shader.h",
"painting/image.cc",
"painting/image.h",
"painting/mask_filter.cc",
"painting/mask_filter.h",
"painting/matrix.cc",
......@@ -34,10 +34,10 @@ source_set("ui") {
"painting/paint.h",
"painting/path.cc",
"painting/path.h",
"painting/picture_recorder.cc",
"painting/picture_recorder.h",
"painting/picture.cc",
"painting/picture.h",
"painting/picture_recorder.cc",
"painting/picture_recorder.h",
"painting/resource_context.cc",
"painting/resource_context.h",
"painting/rrect.cc",
......@@ -46,22 +46,24 @@ source_set("ui") {
"painting/shader.h",
"semantics/semantics_node.cc",
"semantics/semantics_node.h",
"semantics/semantics_update_builder.cc",
"semantics/semantics_update_builder.h",
"semantics/semantics_update.cc",
"semantics/semantics_update.h",
"text/paragraph_builder.cc",
"text/paragraph_builder.h",
"semantics/semantics_update_builder.cc",
"semantics/semantics_update_builder.h",
"text/paragraph.cc",
"text/paragraph.h",
"text/paragraph_builder.cc",
"text/paragraph_builder.h",
"text/text_box.cc",
"text/text_box.h",
"ui_dart_state.cc",
"ui_dart_state.h",
"window/pointer_data_packet.cc",
"window/pointer_data_packet.h",
"window/platform_message.cc",
"window/platform_message.h",
"window/pointer_data.cc",
"window/pointer_data.h",
"window/pointer_data_packet.cc",
"window/pointer_data_packet.h",
"window/window.cc",
"window/window.h",
]
......
......@@ -10,16 +10,16 @@
#include "flutter/lib/ui/mojo_services.h"
#include "flutter/lib/ui/painting/canvas.h"
#include "flutter/lib/ui/painting/gradient.h"
#include "flutter/lib/ui/painting/image.h"
#include "flutter/lib/ui/painting/image_decoding.h"
#include "flutter/lib/ui/painting/image_filter.h"
#include "flutter/lib/ui/painting/image_shader.h"
#include "flutter/lib/ui/painting/image.h"
#include "flutter/lib/ui/painting/mask_filter.h"
#include "flutter/lib/ui/painting/path.h"
#include "flutter/lib/ui/painting/picture_recorder.h"
#include "flutter/lib/ui/painting/picture.h"
#include "flutter/lib/ui/text/paragraph_builder.h"
#include "flutter/lib/ui/painting/picture_recorder.h"
#include "flutter/lib/ui/text/paragraph.h"
#include "flutter/lib/ui/text/paragraph_builder.h"
#include "flutter/lib/ui/window/window.h"
#include "lib/ftl/build_config.h"
#include "lib/tonic/converter/dart_converter.h"
......
......@@ -5,7 +5,10 @@
#ifndef FLUTTER_LIB_UI_UI_DART_STATE_H_
#define FLUTTER_LIB_UI_UI_DART_STATE_H_
#include <utility>
#include "dart/runtime/include/dart_api.h"
#include "flutter/lib/ui/window/platform_message.h"
#include "flutter/sky/engine/wtf/RefPtr.h"
#include "lib/ftl/build_config.h"
#include "lib/tonic/dart_persistent_value.h"
......@@ -46,6 +49,14 @@ class UIDartState : public tonic::DartState {
DartJniIsolateData* jni_data();
#endif
void set_platform_message_sink(PlatformMessage::Sink sink) {
platform_message_sink_ = std::move(sink);
}
const PlatformMessage::Sink& platform_message_sink() const {
return platform_message_sink_;
}
void set_font_selector(PassRefPtr<FontSelector> selector);
PassRefPtr<FontSelector> font_selector();
......@@ -57,6 +68,7 @@ class UIDartState : public tonic::DartState {
std::string debug_name_;
std::unique_ptr<MojoServices> mojo_services_;
std::unique_ptr<Window> window_;
PlatformMessage::Sink platform_message_sink_;
RefPtr<FontSelector> font_selector_;
#if defined(OS_ANDROID)
......
......@@ -19,6 +19,8 @@ typedef void SemanticsActionCallback(int id, SemanticsAction action);
/// Signature for [Window.onAppLifecycleStateChanged].
typedef void AppLifecycleStateCallback(AppLifecycleState state);
typedef void PlatformMessageResponseCallback(ByteData data);
/// States that an application can be in.
enum AppLifecycleState {
// These values must match the order of the values of
......@@ -212,6 +214,16 @@ class Window {
/// In either case, this function disposes the given update, which means the
/// semantics update cannot be used further.
void updateSemantics(SemanticsUpdate update) native "Window_updateSemantics";
void sendPlatformMesssage(String name,
ByteData data,
PlatformMessageResponseCallback callback) {
_sendPlatformMesssage(name, callback, data);
}
void _sendPlatformMesssage(String name,
PlatformMessageResponseCallback callback,
ByteData data) native "Window_sendPlatformMesssage";
}
/// The [Window] singleton. This object exposes the size of the display, the
......
// Copyright 2016 The Chromium 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/lib/ui/window/platform_message.h"
#include <utility>
#include "flutter/common/threads.h"
#include "lib/ftl/functional/wrap_lambda.h"
#include "lib/tonic/dart_state.h"
#include "lib/tonic/logging/dart_invoke.h"
namespace blink {
PlatformMessage::PlatformMessage(std::string name,
std::vector<char> data,
tonic::DartPersistentValue callback)
: name_(std::move(name)),
data_(std::move(data)),
callback_(std::move(callback)) {}
PlatformMessage::~PlatformMessage() {
if (!callback_.is_empty()) {
Threads::UI()->PostTask(
ftl::WrapLambda([callback = std::move(callback_)]() mutable {
callback.Clear();
}));
}
}
void PlatformMessage::InvokeCallback(std::vector<char> data) {
if (callback_.is_empty())
return;
Threads::UI()->PostTask(ftl::WrapLambda(
[ callback = std::move(callback_), data = std::move(data) ]() mutable {
tonic::DartState* dart_state = callback.dart_state().get();
if (!dart_state)
return;
tonic::DartState::Scope scope(dart_state);
Dart_Handle byte_buffer;
if (data.empty()) {
byte_buffer = Dart_Null();
} else {
byte_buffer =
Dart_NewTypedData(Dart_TypedData_kByteData, data.size());
DART_CHECK_VALID(byte_buffer);
void* buffer;
intptr_t length;
Dart_TypedData_Type type;
DART_CHECK_VALID(
Dart_TypedDataAcquireData(byte_buffer, &type, &buffer, &length));
FTL_CHECK(type = Dart_TypedData_kByteData);
FTL_CHECK(length = data.size());
memcpy(buffer, data.data(), length);
Dart_TypedDataReleaseData(byte_buffer);
}
tonic::DartInvoke(callback.Release(), {byte_buffer});
}));
}
void PlatformMessage::InvokeCallbackWithError() {
InvokeCallback(std::vector<char>());
}
void PlatformMessage::ClearData() {
data_.clear();
}
} // namespace blink
// Copyright 2016 The Chromium 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 FLUTTER_LIB_UI_PLATFORM_PLATFORM_MESSAGE_H_
#define FLUTTER_LIB_UI_PLATFORM_PLATFORM_MESSAGE_H_
#include <functional>
#include <string>
#include <vector>
#include "lib/ftl/memory/ref_counted.h"
#include "lib/ftl/memory/ref_ptr.h"
#include "lib/tonic/dart_persistent_value.h"
namespace blink {
class PlatformMessage : public ftl::RefCountedThreadSafe<PlatformMessage> {
FRIEND_REF_COUNTED_THREAD_SAFE(PlatformMessage);
FRIEND_MAKE_REF_COUNTED(PlatformMessage);
public:
using Sink = std::function<void(ftl::RefPtr<PlatformMessage>)>;
const std::string& name() const { return name_; }
const std::vector<char>& data() const { return data_; }
bool has_callback() const { return !callback_.is_empty(); }
// Callable on any thread.
void InvokeCallback(std::vector<char> data);
void InvokeCallbackWithError();
void ClearData();
private:
PlatformMessage(std::string name,
std::vector<char> data,
tonic::DartPersistentValue callback);
~PlatformMessage();
std::string name_;
std::vector<char> data_;
tonic::DartPersistentValue callback_;
};
} // namespace blink
#endif // FLUTTER_LIB_UI_PLATFORM_PLATFORM_MESSAGE_H_
......@@ -7,8 +7,10 @@
#include "flutter/lib/ui/compositing/scene.h"
#include "flutter/lib/ui/ui_dart_state.h"
#include "lib/tonic/converter/dart_converter.h"
#include "lib/tonic/dart_args.h"
#include "lib/tonic/dart_library_natives.h"
#include "lib/tonic/logging/dart_invoke.h"
#include "lib/tonic/typed_data/dart_byte_data.h"
using tonic::DartInvokeField;
using tonic::DartState;
......@@ -33,6 +35,26 @@ void Render(Dart_NativeArguments args) {
UIDartState::Current()->window()->client()->Render(scene);
}
void SendPlatformMessage(Dart_Handle window,
const std::string& name,
Dart_Handle callback,
const tonic::DartByteData& data) {
UIDartState* dart_state = UIDartState::Current();
const char* buffer = static_cast<const char*>(data.data());
auto message = ftl::MakeRefCounted<blink::PlatformMessage>(
name, std::vector<char>(buffer, buffer + data.length_in_bytes()),
tonic::DartPersistentValue(dart_state, callback));
if (const auto& sink = dart_state->platform_message_sink()) {
sink(std::move(message));
} else {
message->InvokeCallbackWithError();
}
}
void _SendPlatformMessage(Dart_NativeArguments args) {
tonic::DartCallStatic(&SendPlatformMessage, args);
}
} // namespace
WindowClient::~WindowClient() {}
......@@ -166,10 +188,10 @@ void Window::OnAppLifecycleStateChanged(sky::AppLifecycleState state) {
}
void Window::RegisterNatives(tonic::DartLibraryNatives* natives) {
natives->Register({
{"Window_scheduleFrame", ScheduleFrame, 1, true},
{"Window_render", Render, 2, true},
});
natives->Register(
{{"Window_scheduleFrame", ScheduleFrame, 1, true},
{"Window_render", Render, 2, true},
{"Window_sendPlatformMessage", _SendPlatformMessage, 4, true}});
}
} // namespace blink
......@@ -7,6 +7,7 @@
#include "flutter/assets/zip_asset_store.h"
#include "flutter/glue/drain_data_pipe_job.h"
#include "flutter/lib/ui/window/platform_message.h"
#include "flutter/runtime/runtime_controller.h"
#include "flutter/runtime/runtime_delegate.h"
#include "flutter/services/engine/sky_engine.mojom.h"
......
......@@ -94,6 +94,8 @@ Shell::Shell() {
io_thread_->StartWithOptions(options);
blink::Threads threads(ftl::MakeRefCounted<glue::TaskRunnerAdaptor>(
base::MessageLoop::current()->task_runner()),
ftl::MakeRefCounted<glue::TaskRunnerAdaptor>(
gpu_thread_->message_loop()->task_runner()),
ftl::MakeRefCounted<glue::TaskRunnerAdaptor>(
ui_thread_->message_loop()->task_runner()),
......
......@@ -40,6 +40,7 @@ shared_library("sky_shell") {
"//flutter/common",
"//flutter/flow",
"//flutter/lib/jni",
"//flutter/lib/ui",
"//flutter/runtime",
"//flutter/shell/common",
"//flutter/shell/gpu",
......
......@@ -33,6 +33,7 @@ import android.view.inputmethod.InputConnection;
import org.json.JSONException;
import org.json.JSONObject;
import org.chromium.base.CalledByNative;
import org.chromium.base.JNINamespace;
import org.chromium.mojo.bindings.Interface.Binding;
import org.chromium.mojo.bindings.InterfaceRequest;
......@@ -53,6 +54,7 @@ import org.chromium.mojom.sky.ViewportMetrics;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
......@@ -577,6 +579,29 @@ public class FlutterView extends SurfaceView
private static native void nativeDispatchPointerDataPacket(long nativePlatformViewAndroid, ByteBuffer buffer, int position);
private static native void nativeInvokePlatformMessageResponseCallback(long nativePlatformViewAndroid, int responseId, String buffer);
@CalledByNative
private void handlePlatformMessage(String messageName, String message, final int responseId) {
OnMessageListener listener = mOnMessageListeners.get(messageName);
if (listener != null) {
nativeInvokePlatformMessageResponseCallback(mNativePlatformView, responseId, listener.onMessage(this, message));
return;
}
OnMessageListenerAsync asyncListener = mAsyncOnMessageListeners.get(messageName);
if (asyncListener != null) {
asyncListener.onMessage(this, message, new MessageResponse() {
@Override
public void send(String response) {
nativeInvokePlatformMessageResponseCallback(mNativePlatformView, responseId, response);
}
});
return;
}
nativeInvokePlatformMessageResponseCallback(mNativePlatformView, responseId, null);
}
// ACCESSIBILITY
......
......@@ -12,6 +12,9 @@
#include <memory>
#include <utility>
#include "base/android/jni_android.h"
#include "base/android/jni_string.h"
#include "base/bind.h"
#include "base/location.h"
#include "base/trace_event/trace_event.h"
#include "flutter/common/threads.h"
#include "flutter/flow/compositor_context.h"
......@@ -106,6 +109,56 @@ void PlatformViewAndroid::DispatchPointerDataPacket(JNIEnv* env,
}));
}
void PlatformViewAndroid::InvokePlatformMessageResponseCallback(
JNIEnv* env,
jobject obj,
jint response_id,
jstring java_response) {
if (!response_id)
return;
auto it = pending_messages_.find(response_id);
if (it == pending_messages_.end())
return;
std::string response =
base::android::ConvertJavaStringToUTF8(env, java_response);
// TODO(abarth): There's an extra copy here.
it->second->InvokeCallback(
std::vector<char>(response.data(), response.data() + response.size()));
pending_messages_.erase(it);
}
void PlatformViewAndroid::HandlePlatformMessage(
ftl::RefPtr<blink::PlatformMessage> message) {
JNIEnv* env = base::android::AttachCurrentThread();
{
base::android::ScopedJavaLocalRef<jobject> view = flutter_view_.get(env);
if (view.is_null())
return;
int response_id = 0;
if (message->has_callback()) {
response_id = next_response_id_++;
pending_messages_[response_id] = message;
}
base::StringPiece message_name = message->name();
auto data = message->data();
base::StringPiece message_data(data.data(), data.size());
auto java_message_name =
base::android::ConvertUTF8ToJavaString(env, message_name);
auto java_message_data =
base::android::ConvertUTF8ToJavaString(env, message_data);
message->ClearData();
// This call can re-enter in InvokePlatformMessageResponseCallback.
Java_FlutterView_handlePlatformMessage(
env, view.obj(), java_message_name.obj(), java_message_data.obj(),
response_id);
}
}
void PlatformViewAndroid::ReleaseSurface() {
if (surface_gl_) {
NotifyDestroyed();
......
......@@ -5,11 +5,13 @@
#ifndef SHELL_PLATFORM_ANDROID_PLATFORM_VIEW_ANDROID_H_
#define SHELL_PLATFORM_ANDROID_PLATFORM_VIEW_ANDROID_H_
#include <memory>
#include <string>
#include <unordered_map>
#include <memory>
#include "base/android/jni_android.h"
#include "base/android/jni_weak_ref.h"
#include "flutter/lib/ui/window/platform_message.h"
#include "flutter/shell/common/platform_view.h"
#include "flutter/shell/platform/android/android_surface_gl.h"
#include "lib/ftl/memory/weak_ptr.h"
......@@ -37,6 +39,11 @@ class PlatformViewAndroid : public PlatformView {
jobject buffer,
jint position);
void InvokePlatformMessageResponseCallback(JNIEnv* env,
jobject obj,
jint response_id,
jstring response);
base::android::ScopedJavaLocalRef<jobject> GetBitmap(JNIEnv* env,
jobject obj);
......@@ -61,6 +68,11 @@ class PlatformViewAndroid : public PlatformView {
JavaObjectWeakGlobalRef flutter_view_;
ftl::WeakPtrFactory<PlatformViewAndroid> weak_factory_;
// We use id 0 to mean that no response is expected.
int next_response_id_ = 1;
std::unordered_map<int, ftl::RefPtr<blink::PlatformMessage>>
pending_messages_;
void UpdateThreadPriorities();
void ReleaseSurface();
......@@ -69,6 +81,8 @@ class PlatformViewAndroid : public PlatformView {
jobject* pixels_out,
SkISize* size_out);
void HandlePlatformMessage(ftl::RefPtr<blink::PlatformMessage> message);
FTL_DISALLOW_COPY_AND_ASSIGN(PlatformViewAndroid);
};
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册