2018-11-07 12:24:35 -08:00
|
|
|
// Copyright 2013 The Flutter Authors. All rights reserved.
|
2015-01-31 00:44:42 -08:00
|
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
|
|
|
// found in the LICENSE file.
|
|
|
|
|
|
2016-09-23 15:33:25 -07:00
|
|
|
#include "flutter/shell/platform/android/platform_view_android.h"
|
2015-01-31 00:44:42 -08:00
|
|
|
|
2018-04-13 13:48:15 -07:00
|
|
|
#include <memory>
|
2016-07-12 14:47:44 -07:00
|
|
|
#include <utility>
|
2017-01-20 14:37:10 -08:00
|
|
|
|
2018-07-20 10:12:38 -07:00
|
|
|
#include "flutter/fml/synchronization/waitable_event.h"
|
2019-04-09 17:10:46 -07:00
|
|
|
#include "flutter/shell/common/shell_io_manager.h"
|
2019-02-20 17:23:14 -08:00
|
|
|
#include "flutter/shell/gpu/gpu_surface_gl_delegate.h"
|
2017-11-02 02:57:29 -07:00
|
|
|
#include "flutter/shell/platform/android/android_external_texture_gl.h"
|
2017-01-20 14:37:10 -08:00
|
|
|
#include "flutter/shell/platform/android/android_surface_gl.h"
|
2018-04-13 13:48:15 -07:00
|
|
|
#include "flutter/shell/platform/android/platform_message_response_android.h"
|
2017-03-22 15:42:51 -07:00
|
|
|
#include "flutter/shell/platform/android/platform_view_android_jni.h"
|
2016-10-24 16:14:37 -07:00
|
|
|
#include "flutter/shell/platform/android/vsync_waiter_android.h"
|
2015-01-31 00:44:42 -08:00
|
|
|
|
2019-04-09 17:10:46 -07:00
|
|
|
namespace flutter {
|
2016-10-17 16:47:42 -07:00
|
|
|
|
2018-04-13 13:48:15 -07:00
|
|
|
PlatformViewAndroid::PlatformViewAndroid(
|
|
|
|
|
PlatformView::Delegate& delegate,
|
2019-04-09 12:44:42 -07:00
|
|
|
flutter::TaskRunners task_runners,
|
2018-04-13 13:48:15 -07:00
|
|
|
fml::jni::JavaObjectWeakGlobalRef java_object,
|
|
|
|
|
bool use_software_rendering)
|
|
|
|
|
: PlatformView(delegate, std::move(task_runners)),
|
|
|
|
|
java_object_(java_object),
|
|
|
|
|
android_surface_(AndroidSurface::Create(use_software_rendering)) {
|
2018-07-26 12:49:34 -07:00
|
|
|
FML_CHECK(android_surface_)
|
2018-04-13 13:48:15 -07:00
|
|
|
<< "Could not create an OpenGL, Vulkan or Software surface to setup "
|
|
|
|
|
"rendering.";
|
2017-01-20 14:37:10 -08:00
|
|
|
}
|
|
|
|
|
|
2018-08-07 12:42:22 -07:00
|
|
|
PlatformViewAndroid::PlatformViewAndroid(
|
|
|
|
|
PlatformView::Delegate& delegate,
|
2019-04-09 12:44:42 -07:00
|
|
|
flutter::TaskRunners task_runners,
|
2018-08-07 12:42:22 -07:00
|
|
|
fml::jni::JavaObjectWeakGlobalRef java_object)
|
|
|
|
|
: PlatformView(delegate, std::move(task_runners)),
|
|
|
|
|
java_object_(java_object),
|
|
|
|
|
android_surface_(nullptr) {}
|
|
|
|
|
|
2017-07-12 10:25:42 -07:00
|
|
|
PlatformViewAndroid::~PlatformViewAndroid() = default;
|
|
|
|
|
|
2018-04-13 13:48:15 -07:00
|
|
|
void PlatformViewAndroid::NotifyCreated(
|
2018-07-26 12:49:34 -07:00
|
|
|
fml::RefPtr<AndroidNativeWindow> native_window) {
|
2018-08-07 12:42:22 -07:00
|
|
|
if (android_surface_) {
|
|
|
|
|
InstallFirstFrameCallback();
|
2019-03-20 17:43:53 -07:00
|
|
|
|
|
|
|
|
fml::AutoResetWaitableEvent latch;
|
|
|
|
|
fml::TaskRunner::RunNowOrPostTask(
|
|
|
|
|
task_runners_.GetGPUTaskRunner(),
|
|
|
|
|
[&latch, surface = android_surface_.get(),
|
|
|
|
|
native_window = std::move(native_window)]() {
|
|
|
|
|
surface->SetNativeWindow(native_window);
|
|
|
|
|
latch.Signal();
|
|
|
|
|
});
|
|
|
|
|
latch.Wait();
|
2018-08-07 12:42:22 -07:00
|
|
|
}
|
2019-03-20 17:43:53 -07:00
|
|
|
|
2018-04-13 13:48:15 -07:00
|
|
|
PlatformView::NotifyCreated();
|
2016-10-24 16:14:37 -07:00
|
|
|
}
|
2015-06-12 13:29:53 -07:00
|
|
|
|
2018-04-13 13:48:15 -07:00
|
|
|
void PlatformViewAndroid::NotifyDestroyed() {
|
|
|
|
|
PlatformView::NotifyDestroyed();
|
2019-03-20 17:43:53 -07:00
|
|
|
|
2018-08-07 12:42:22 -07:00
|
|
|
if (android_surface_) {
|
2019-03-20 17:43:53 -07:00
|
|
|
fml::AutoResetWaitableEvent latch;
|
|
|
|
|
fml::TaskRunner::RunNowOrPostTask(
|
|
|
|
|
task_runners_.GetGPUTaskRunner(),
|
|
|
|
|
[&latch, surface = android_surface_.get()]() {
|
|
|
|
|
surface->TeardownOnScreenContext();
|
|
|
|
|
latch.Signal();
|
|
|
|
|
});
|
|
|
|
|
latch.Wait();
|
2018-08-07 12:42:22 -07:00
|
|
|
}
|
2015-01-31 00:44:42 -08:00
|
|
|
}
|
|
|
|
|
|
2018-04-13 13:48:15 -07:00
|
|
|
void PlatformViewAndroid::NotifyChanged(const SkISize& size) {
|
2018-08-07 12:42:22 -07:00
|
|
|
if (!android_surface_) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2018-07-20 10:12:38 -07:00
|
|
|
fml::AutoResetWaitableEvent latch;
|
2018-04-13 13:48:15 -07:00
|
|
|
fml::TaskRunner::RunNowOrPostTask(
|
|
|
|
|
task_runners_.GetGPUTaskRunner(), //
|
|
|
|
|
[&latch, surface = android_surface_.get(), size]() {
|
|
|
|
|
surface->OnScreenSurfaceResize(size);
|
|
|
|
|
latch.Signal();
|
2018-03-06 10:40:19 -08:00
|
|
|
});
|
2018-04-13 13:48:15 -07:00
|
|
|
latch.Wait();
|
2016-10-27 13:12:55 -07:00
|
|
|
}
|
|
|
|
|
|
2016-10-17 16:47:42 -07:00
|
|
|
void PlatformViewAndroid::DispatchPlatformMessage(JNIEnv* env,
|
2017-03-22 15:42:51 -07:00
|
|
|
std::string name,
|
2017-03-01 13:54:32 +01:00
|
|
|
jobject java_message_data,
|
|
|
|
|
jint java_message_position,
|
2016-10-17 16:47:42 -07:00
|
|
|
jint response_id) {
|
2017-04-09 00:07:28 +02:00
|
|
|
uint8_t* message_data =
|
|
|
|
|
static_cast<uint8_t*>(env->GetDirectBufferAddress(java_message_data));
|
|
|
|
|
std::vector<uint8_t> message =
|
|
|
|
|
std::vector<uint8_t>(message_data, message_data + java_message_position);
|
2017-03-01 13:54:32 +01:00
|
|
|
|
2019-04-09 12:44:42 -07:00
|
|
|
fml::RefPtr<flutter::PlatformMessageResponse> response;
|
2016-10-17 16:47:42 -07:00
|
|
|
if (response_id) {
|
2018-07-26 12:49:34 -07:00
|
|
|
response = fml::MakeRefCounted<PlatformMessageResponseAndroid>(
|
2018-04-13 13:48:15 -07:00
|
|
|
response_id, java_object_, task_runners_.GetPlatformTaskRunner());
|
2016-10-17 16:47:42 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PlatformView::DispatchPlatformMessage(
|
2019-04-09 12:44:42 -07:00
|
|
|
fml::MakeRefCounted<flutter::PlatformMessage>(
|
2017-03-22 15:42:51 -07:00
|
|
|
std::move(name), std::move(message), std::move(response)));
|
2016-10-17 16:47:42 -07:00
|
|
|
}
|
|
|
|
|
|
2017-04-09 00:07:28 +02:00
|
|
|
void PlatformViewAndroid::DispatchEmptyPlatformMessage(JNIEnv* env,
|
|
|
|
|
std::string name,
|
|
|
|
|
jint response_id) {
|
2019-04-09 12:44:42 -07:00
|
|
|
fml::RefPtr<flutter::PlatformMessageResponse> response;
|
2017-04-09 00:07:28 +02:00
|
|
|
if (response_id) {
|
2018-07-26 12:49:34 -07:00
|
|
|
response = fml::MakeRefCounted<PlatformMessageResponseAndroid>(
|
2018-04-13 13:48:15 -07:00
|
|
|
response_id, java_object_, task_runners_.GetPlatformTaskRunner());
|
2017-04-09 00:07:28 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PlatformView::DispatchPlatformMessage(
|
2019-04-09 12:44:42 -07:00
|
|
|
fml::MakeRefCounted<flutter::PlatformMessage>(std::move(name),
|
|
|
|
|
std::move(response)));
|
2017-04-09 00:07:28 +02:00
|
|
|
}
|
|
|
|
|
|
2016-10-07 12:05:43 -07:00
|
|
|
void PlatformViewAndroid::InvokePlatformMessageResponseCallback(
|
|
|
|
|
JNIEnv* env,
|
|
|
|
|
jint response_id,
|
2017-03-01 13:54:32 +01:00
|
|
|
jobject java_response_data,
|
|
|
|
|
jint java_response_position) {
|
2016-10-07 12:05:43 -07:00
|
|
|
if (!response_id)
|
|
|
|
|
return;
|
2016-10-14 15:51:25 -07:00
|
|
|
auto it = pending_responses_.find(response_id);
|
|
|
|
|
if (it == pending_responses_.end())
|
2016-10-07 12:05:43 -07:00
|
|
|
return;
|
2017-04-09 00:07:28 +02:00
|
|
|
uint8_t* response_data =
|
2017-05-31 17:27:47 -07:00
|
|
|
static_cast<uint8_t*>(env->GetDirectBufferAddress(java_response_data));
|
|
|
|
|
std::vector<uint8_t> response = std::vector<uint8_t>(
|
|
|
|
|
response_data, response_data + java_response_position);
|
2016-10-14 16:01:23 -07:00
|
|
|
auto message_response = std::move(it->second);
|
2016-10-14 15:51:25 -07:00
|
|
|
pending_responses_.erase(it);
|
2018-06-19 14:24:19 -07:00
|
|
|
message_response->Complete(
|
|
|
|
|
std::make_unique<fml::DataMapping>(std::move(response)));
|
2016-10-07 12:05:43 -07:00
|
|
|
}
|
|
|
|
|
|
2017-04-09 00:07:28 +02:00
|
|
|
void PlatformViewAndroid::InvokePlatformMessageEmptyResponseCallback(
|
|
|
|
|
JNIEnv* env,
|
|
|
|
|
jint response_id) {
|
|
|
|
|
if (!response_id)
|
|
|
|
|
return;
|
|
|
|
|
auto it = pending_responses_.find(response_id);
|
|
|
|
|
if (it == pending_responses_.end())
|
|
|
|
|
return;
|
|
|
|
|
auto message_response = std::move(it->second);
|
|
|
|
|
pending_responses_.erase(it);
|
|
|
|
|
message_response->CompleteEmpty();
|
|
|
|
|
}
|
|
|
|
|
|
2019-04-09 17:10:46 -07:00
|
|
|
// |PlatformView|
|
2016-10-07 12:05:43 -07:00
|
|
|
void PlatformViewAndroid::HandlePlatformMessage(
|
2019-04-09 12:44:42 -07:00
|
|
|
fml::RefPtr<flutter::PlatformMessage> message) {
|
2017-03-22 15:42:51 -07:00
|
|
|
JNIEnv* env = fml::jni::AttachCurrentThread();
|
2018-04-13 13:48:15 -07:00
|
|
|
fml::jni::ScopedJavaLocalRef<jobject> view = java_object_.get(env);
|
2016-10-17 16:47:42 -07:00
|
|
|
if (view.is_null())
|
|
|
|
|
return;
|
2016-10-07 12:05:43 -07:00
|
|
|
|
2016-10-17 16:47:42 -07:00
|
|
|
int response_id = 0;
|
|
|
|
|
if (auto response = message->response()) {
|
|
|
|
|
response_id = next_response_id_++;
|
|
|
|
|
pending_responses_[response_id] = response;
|
2016-10-07 12:05:43 -07:00
|
|
|
}
|
2017-03-22 15:42:51 -07:00
|
|
|
auto java_channel = fml::jni::StringToJavaString(env, message->channel());
|
2017-04-09 00:07:28 +02:00
|
|
|
if (message->hasData()) {
|
2017-05-31 17:27:47 -07:00
|
|
|
fml::jni::ScopedJavaLocalRef<jbyteArray> message_array(
|
|
|
|
|
env, env->NewByteArray(message->data().size()));
|
2017-04-09 00:07:28 +02:00
|
|
|
env->SetByteArrayRegion(
|
|
|
|
|
message_array.obj(), 0, message->data().size(),
|
|
|
|
|
reinterpret_cast<const jbyte*>(message->data().data()));
|
|
|
|
|
message = nullptr;
|
2016-10-17 16:47:42 -07:00
|
|
|
|
2017-04-09 00:07:28 +02:00
|
|
|
// This call can re-enter in InvokePlatformMessageXxxResponseCallback.
|
2017-05-31 17:27:47 -07:00
|
|
|
FlutterViewHandlePlatformMessage(env, view.obj(), java_channel.obj(),
|
|
|
|
|
message_array.obj(), response_id);
|
2017-04-09 00:07:28 +02:00
|
|
|
} else {
|
|
|
|
|
message = nullptr;
|
|
|
|
|
|
|
|
|
|
// This call can re-enter in InvokePlatformMessageXxxResponseCallback.
|
2017-05-31 17:27:47 -07:00
|
|
|
FlutterViewHandlePlatformMessage(env, view.obj(), java_channel.obj(),
|
|
|
|
|
nullptr, response_id);
|
2017-04-09 00:07:28 +02:00
|
|
|
}
|
2016-10-17 16:47:42 -07:00
|
|
|
}
|
|
|
|
|
|
2019-04-09 17:10:46 -07:00
|
|
|
// |PlatformView|
|
2018-08-03 08:54:12 -07:00
|
|
|
void PlatformViewAndroid::OnPreEngineRestart() const {
|
|
|
|
|
JNIEnv* env = fml::jni::AttachCurrentThread();
|
|
|
|
|
fml::jni::ScopedJavaLocalRef<jobject> view = java_object_.get(env);
|
|
|
|
|
if (view.is_null()) {
|
|
|
|
|
// The Java object died.
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
FlutterViewOnPreEngineRestart(fml::jni::AttachCurrentThread(), view.obj());
|
|
|
|
|
}
|
|
|
|
|
|
2017-12-12 14:25:45 -08:00
|
|
|
void PlatformViewAndroid::DispatchSemanticsAction(JNIEnv* env,
|
|
|
|
|
jint id,
|
|
|
|
|
jint action,
|
|
|
|
|
jobject args,
|
|
|
|
|
jint args_position) {
|
|
|
|
|
if (env->IsSameObject(args, NULL)) {
|
|
|
|
|
std::vector<uint8_t> args_vector;
|
|
|
|
|
PlatformView::DispatchSemanticsAction(
|
2019-04-09 12:44:42 -07:00
|
|
|
id, static_cast<flutter::SemanticsAction>(action), args_vector);
|
2017-12-12 14:25:45 -08:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint8_t* args_data = static_cast<uint8_t*>(env->GetDirectBufferAddress(args));
|
|
|
|
|
std::vector<uint8_t> args_vector =
|
|
|
|
|
std::vector<uint8_t>(args_data, args_data + args_position);
|
|
|
|
|
|
2016-10-11 10:52:48 -07:00
|
|
|
PlatformView::DispatchSemanticsAction(
|
2019-04-09 12:44:42 -07:00
|
|
|
id, static_cast<flutter::SemanticsAction>(action),
|
|
|
|
|
std::move(args_vector));
|
2016-10-11 10:52:48 -07:00
|
|
|
}
|
|
|
|
|
|
2019-04-09 17:10:46 -07:00
|
|
|
// |PlatformView|
|
2018-07-17 11:58:42 -07:00
|
|
|
void PlatformViewAndroid::UpdateSemantics(
|
2019-04-09 12:44:42 -07:00
|
|
|
flutter::SemanticsNodeUpdates update,
|
|
|
|
|
flutter::CustomAccessibilityActionUpdates actions) {
|
2019-09-16 09:37:25 -07:00
|
|
|
constexpr size_t kBytesPerNode = 41 * sizeof(int32_t);
|
2016-10-11 10:52:48 -07:00
|
|
|
constexpr size_t kBytesPerChild = sizeof(int32_t);
|
2018-07-25 15:26:02 -07:00
|
|
|
constexpr size_t kBytesPerAction = 4 * sizeof(int32_t);
|
2016-10-11 10:52:48 -07:00
|
|
|
|
2017-03-22 15:42:51 -07:00
|
|
|
JNIEnv* env = fml::jni::AttachCurrentThread();
|
2016-10-11 10:52:48 -07:00
|
|
|
{
|
2018-04-13 13:48:15 -07:00
|
|
|
fml::jni::ScopedJavaLocalRef<jobject> view = java_object_.get(env);
|
2016-10-11 10:52:48 -07:00
|
|
|
if (view.is_null())
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
size_t num_bytes = 0;
|
2018-02-05 16:11:51 -08:00
|
|
|
for (const auto& value : update) {
|
2016-10-11 10:52:48 -07:00
|
|
|
num_bytes += kBytesPerNode;
|
2018-06-19 14:24:19 -07:00
|
|
|
num_bytes +=
|
|
|
|
|
value.second.childrenInTraversalOrder.size() * kBytesPerChild;
|
2018-05-21 17:44:23 -07:00
|
|
|
num_bytes += value.second.childrenInHitTestOrder.size() * kBytesPerChild;
|
2018-07-17 11:58:42 -07:00
|
|
|
num_bytes +=
|
|
|
|
|
value.second.customAccessibilityActions.size() * kBytesPerChild;
|
2016-10-11 10:52:48 -07:00
|
|
|
}
|
|
|
|
|
|
2016-10-19 16:49:36 -07:00
|
|
|
std::vector<uint8_t> buffer(num_bytes);
|
2016-10-11 10:52:48 -07:00
|
|
|
int32_t* buffer_int32 = reinterpret_cast<int32_t*>(&buffer[0]);
|
|
|
|
|
float* buffer_float32 = reinterpret_cast<float*>(&buffer[0]);
|
|
|
|
|
|
|
|
|
|
std::vector<std::string> strings;
|
|
|
|
|
size_t position = 0;
|
2018-02-05 16:11:51 -08:00
|
|
|
for (const auto& value : update) {
|
2017-08-28 16:12:39 -07:00
|
|
|
// If you edit this code, make sure you update kBytesPerNode
|
2018-01-30 13:42:12 -08:00
|
|
|
// and/or kBytesPerChild above to match the number of values you are
|
|
|
|
|
// sending.
|
2019-04-09 12:44:42 -07:00
|
|
|
const flutter::SemanticsNode& node = value.second;
|
2016-10-11 10:52:48 -07:00
|
|
|
buffer_int32[position++] = node.id;
|
|
|
|
|
buffer_int32[position++] = node.flags;
|
|
|
|
|
buffer_int32[position++] = node.actions;
|
2019-09-16 09:37:25 -07:00
|
|
|
buffer_int32[position++] = node.maxValueLength;
|
|
|
|
|
buffer_int32[position++] = node.currentValueLength;
|
2018-01-24 16:54:14 -08:00
|
|
|
buffer_int32[position++] = node.textSelectionBase;
|
|
|
|
|
buffer_int32[position++] = node.textSelectionExtent;
|
2019-03-11 11:30:35 -07:00
|
|
|
buffer_int32[position++] = node.platformViewId;
|
2018-09-13 10:28:27 -07:00
|
|
|
buffer_int32[position++] = node.scrollChildren;
|
|
|
|
|
buffer_int32[position++] = node.scrollIndex;
|
2018-02-09 15:39:58 -08:00
|
|
|
buffer_float32[position++] = (float)node.scrollPosition;
|
|
|
|
|
buffer_float32[position++] = (float)node.scrollExtentMax;
|
|
|
|
|
buffer_float32[position++] = (float)node.scrollExtentMin;
|
2016-10-11 10:52:48 -07:00
|
|
|
if (node.label.empty()) {
|
|
|
|
|
buffer_int32[position++] = -1;
|
|
|
|
|
} else {
|
|
|
|
|
buffer_int32[position++] = strings.size();
|
|
|
|
|
strings.push_back(node.label);
|
|
|
|
|
}
|
2017-10-23 16:46:01 -07:00
|
|
|
if (node.value.empty()) {
|
|
|
|
|
buffer_int32[position++] = -1;
|
|
|
|
|
} else {
|
|
|
|
|
buffer_int32[position++] = strings.size();
|
|
|
|
|
strings.push_back(node.value);
|
|
|
|
|
}
|
2017-10-31 10:03:30 -07:00
|
|
|
if (node.increasedValue.empty()) {
|
|
|
|
|
buffer_int32[position++] = -1;
|
|
|
|
|
} else {
|
|
|
|
|
buffer_int32[position++] = strings.size();
|
|
|
|
|
strings.push_back(node.increasedValue);
|
|
|
|
|
}
|
|
|
|
|
if (node.decreasedValue.empty()) {
|
|
|
|
|
buffer_int32[position++] = -1;
|
|
|
|
|
} else {
|
|
|
|
|
buffer_int32[position++] = strings.size();
|
|
|
|
|
strings.push_back(node.decreasedValue);
|
|
|
|
|
}
|
2017-10-23 16:46:01 -07:00
|
|
|
if (node.hint.empty()) {
|
|
|
|
|
buffer_int32[position++] = -1;
|
|
|
|
|
} else {
|
|
|
|
|
buffer_int32[position++] = strings.size();
|
|
|
|
|
strings.push_back(node.hint);
|
|
|
|
|
}
|
2017-08-28 16:12:39 -07:00
|
|
|
buffer_int32[position++] = node.textDirection;
|
2016-10-11 10:52:48 -07:00
|
|
|
buffer_float32[position++] = node.rect.left();
|
|
|
|
|
buffer_float32[position++] = node.rect.top();
|
|
|
|
|
buffer_float32[position++] = node.rect.right();
|
|
|
|
|
buffer_float32[position++] = node.rect.bottom();
|
|
|
|
|
node.transform.asColMajorf(&buffer_float32[position]);
|
|
|
|
|
position += 16;
|
2018-05-21 17:44:23 -07:00
|
|
|
|
|
|
|
|
buffer_int32[position++] = node.childrenInTraversalOrder.size();
|
|
|
|
|
for (int32_t child : node.childrenInTraversalOrder)
|
|
|
|
|
buffer_int32[position++] = child;
|
|
|
|
|
|
|
|
|
|
for (int32_t child : node.childrenInHitTestOrder)
|
2016-10-11 10:52:48 -07:00
|
|
|
buffer_int32[position++] = child;
|
2018-07-11 10:27:50 -07:00
|
|
|
|
|
|
|
|
buffer_int32[position++] = node.customAccessibilityActions.size();
|
|
|
|
|
for (int32_t child : node.customAccessibilityActions)
|
|
|
|
|
buffer_int32[position++] = child;
|
2016-10-11 10:52:48 -07:00
|
|
|
}
|
|
|
|
|
|
2018-07-11 10:27:50 -07:00
|
|
|
// custom accessibility actions.
|
|
|
|
|
size_t num_action_bytes = actions.size() * kBytesPerAction;
|
|
|
|
|
std::vector<uint8_t> actions_buffer(num_action_bytes);
|
2018-07-17 11:58:42 -07:00
|
|
|
int32_t* actions_buffer_int32 =
|
|
|
|
|
reinterpret_cast<int32_t*>(&actions_buffer[0]);
|
2018-07-11 10:27:50 -07:00
|
|
|
|
|
|
|
|
std::vector<std::string> action_strings;
|
|
|
|
|
size_t actions_position = 0;
|
|
|
|
|
for (const auto& value : actions) {
|
|
|
|
|
// If you edit this code, make sure you update kBytesPerAction
|
|
|
|
|
// to match the number of values you are
|
|
|
|
|
// sending.
|
2019-04-09 12:44:42 -07:00
|
|
|
const flutter::CustomAccessibilityAction& action = value.second;
|
2018-07-11 10:27:50 -07:00
|
|
|
actions_buffer_int32[actions_position++] = action.id;
|
2018-07-25 15:26:02 -07:00
|
|
|
actions_buffer_int32[actions_position++] = action.overrideId;
|
2018-07-11 10:27:50 -07:00
|
|
|
if (action.label.empty()) {
|
|
|
|
|
actions_buffer_int32[actions_position++] = -1;
|
|
|
|
|
} else {
|
|
|
|
|
actions_buffer_int32[actions_position++] = action_strings.size();
|
|
|
|
|
action_strings.push_back(action.label);
|
|
|
|
|
}
|
2018-07-25 15:26:02 -07:00
|
|
|
if (action.hint.empty()) {
|
|
|
|
|
actions_buffer_int32[actions_position++] = -1;
|
|
|
|
|
} else {
|
|
|
|
|
actions_buffer_int32[actions_position++] = action_strings.size();
|
|
|
|
|
action_strings.push_back(action.hint);
|
|
|
|
|
}
|
2018-07-11 10:27:50 -07:00
|
|
|
}
|
|
|
|
|
|
2018-07-17 11:58:42 -07:00
|
|
|
// Calling NewDirectByteBuffer in API level 22 and below with a size of zero
|
|
|
|
|
// will cause a JNI crash.
|
|
|
|
|
if (actions_buffer.size() > 0) {
|
|
|
|
|
fml::jni::ScopedJavaLocalRef<jobject> direct_actions_buffer(
|
|
|
|
|
env, env->NewDirectByteBuffer(actions_buffer.data(),
|
|
|
|
|
actions_buffer.size()));
|
|
|
|
|
FlutterViewUpdateCustomAccessibilityActions(
|
|
|
|
|
env, view.obj(), direct_actions_buffer.obj(),
|
|
|
|
|
fml::jni::VectorToStringArray(env, action_strings).obj());
|
|
|
|
|
}
|
2018-07-11 10:27:50 -07:00
|
|
|
|
2018-07-17 11:58:42 -07:00
|
|
|
if (buffer.size() > 0) {
|
|
|
|
|
fml::jni::ScopedJavaLocalRef<jobject> direct_buffer(
|
|
|
|
|
env, env->NewDirectByteBuffer(buffer.data(), buffer.size()));
|
|
|
|
|
FlutterViewUpdateSemantics(
|
|
|
|
|
env, view.obj(), direct_buffer.obj(),
|
|
|
|
|
fml::jni::VectorToStringArray(env, strings).obj());
|
|
|
|
|
}
|
2016-10-11 10:52:48 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-11-02 02:57:29 -07:00
|
|
|
void PlatformViewAndroid::RegisterExternalTexture(
|
|
|
|
|
int64_t texture_id,
|
|
|
|
|
const fml::jni::JavaObjectWeakGlobalRef& surface_texture) {
|
|
|
|
|
RegisterTexture(
|
|
|
|
|
std::make_shared<AndroidExternalTextureGL>(texture_id, surface_texture));
|
|
|
|
|
}
|
|
|
|
|
|
2019-04-09 17:10:46 -07:00
|
|
|
// |PlatformView|
|
2018-04-13 13:48:15 -07:00
|
|
|
std::unique_ptr<VsyncWaiter> PlatformViewAndroid::CreateVSyncWaiter() {
|
|
|
|
|
return std::make_unique<VsyncWaiterAndroid>(task_runners_);
|
2017-11-02 02:57:29 -07:00
|
|
|
}
|
|
|
|
|
|
2019-04-09 17:10:46 -07:00
|
|
|
// |PlatformView|
|
2018-04-13 13:48:15 -07:00
|
|
|
std::unique_ptr<Surface> PlatformViewAndroid::CreateRenderingSurface() {
|
2018-08-07 12:42:22 -07:00
|
|
|
if (!android_surface_) {
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
2018-04-13 13:48:15 -07:00
|
|
|
return android_surface_->CreateGPUSurface();
|
2016-09-16 14:00:49 -07:00
|
|
|
}
|
|
|
|
|
|
2019-04-09 17:10:46 -07:00
|
|
|
// |PlatformView|
|
2018-04-13 13:48:15 -07:00
|
|
|
sk_sp<GrContext> PlatformViewAndroid::CreateResourceContext() const {
|
2018-08-07 12:42:22 -07:00
|
|
|
if (!android_surface_) {
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
2018-04-13 13:48:15 -07:00
|
|
|
sk_sp<GrContext> resource_context;
|
|
|
|
|
if (android_surface_->ResourceContextMakeCurrent()) {
|
|
|
|
|
// TODO(chinmaygarde): Currently, this code depends on the fact that only
|
|
|
|
|
// the OpenGL surface will be able to make a resource context current. If
|
|
|
|
|
// this changes, this assumption breaks. Handle the same.
|
2019-04-09 17:10:46 -07:00
|
|
|
resource_context = ShellIOManager::CreateCompatibleResourceLoadingContext(
|
2019-02-20 17:23:14 -08:00
|
|
|
GrBackend::kOpenGL_GrBackend,
|
|
|
|
|
GPUSurfaceGLDelegate::GetDefaultPlatformGLInterface());
|
2018-04-13 13:48:15 -07:00
|
|
|
} else {
|
2018-07-26 12:49:34 -07:00
|
|
|
FML_DLOG(ERROR) << "Could not make the resource context current.";
|
2018-04-11 15:41:23 -07:00
|
|
|
}
|
2018-04-12 18:28:55 +02:00
|
|
|
|
2018-04-13 13:48:15 -07:00
|
|
|
return resource_context;
|
|
|
|
|
}
|
2018-04-12 18:28:55 +02:00
|
|
|
|
2019-04-09 17:10:46 -07:00
|
|
|
// |PlatformView|
|
2018-08-14 13:15:42 -07:00
|
|
|
void PlatformViewAndroid::ReleaseResourceContext() const {
|
|
|
|
|
if (android_surface_) {
|
|
|
|
|
android_surface_->ResourceContextClearCurrent();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-04-13 13:48:15 -07:00
|
|
|
void PlatformViewAndroid::InstallFirstFrameCallback() {
|
|
|
|
|
// On Platform Task Runner.
|
|
|
|
|
SetNextFrameCallback(
|
|
|
|
|
[platform_view = GetWeakPtr(),
|
|
|
|
|
platform_task_runner = task_runners_.GetPlatformTaskRunner()]() {
|
|
|
|
|
// On GPU Task Runner.
|
|
|
|
|
platform_task_runner->PostTask([platform_view]() {
|
|
|
|
|
// Back on Platform Task Runner.
|
|
|
|
|
if (platform_view) {
|
|
|
|
|
reinterpret_cast<PlatformViewAndroid*>(platform_view.get())
|
|
|
|
|
->FireFirstFrameCallback();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
}
|
2018-04-12 18:28:55 +02:00
|
|
|
|
2018-04-13 13:48:15 -07:00
|
|
|
void PlatformViewAndroid::FireFirstFrameCallback() {
|
|
|
|
|
JNIEnv* env = fml::jni::AttachCurrentThread();
|
|
|
|
|
fml::jni::ScopedJavaLocalRef<jobject> view = java_object_.get(env);
|
|
|
|
|
if (view.is_null()) {
|
|
|
|
|
// The Java object died.
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
FlutterViewOnFirstFrame(fml::jni::AttachCurrentThread(), view.obj());
|
2016-10-06 15:06:21 -07:00
|
|
|
}
|
|
|
|
|
|
2019-04-09 17:10:46 -07:00
|
|
|
} // namespace flutter
|