Skip to content

Commit

Permalink
fix FlutterViewUpdateCustomAccessibilityActions uses correct string l…
Browse files Browse the repository at this point in the history
…ist (flutter#19623)

* fix FlutterViewUpdateCustomAccessibilityActions uses correct string list

* add test to ci

* format

* add license file

* fix test

* fix lint
  • Loading branch information
chunhtai authored Jul 28, 2020
1 parent c58a69c commit db8c40b
Show file tree
Hide file tree
Showing 10 changed files with 342 additions and 139 deletions.
1 change: 1 addition & 0 deletions BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ group("flutter") {
public_deps += [
"//flutter/shell/platform/android/external_view_embedder:android_external_view_embedder_unittests",
"//flutter/shell/platform/android/jni:jni_unittests",
"//flutter/shell/platform/android/platform_view_android_delegate:platform_view_android_delegate_unittests",
]
}

Expand Down
3 changes: 3 additions & 0 deletions ci/licenses_golden/licenses_flutter
Original file line number Diff line number Diff line change
Expand Up @@ -815,6 +815,9 @@ FILE: ../../../flutter/shell/platform/android/platform_message_response_android.
FILE: ../../../flutter/shell/platform/android/platform_message_response_android.h
FILE: ../../../flutter/shell/platform/android/platform_view_android.cc
FILE: ../../../flutter/shell/platform/android/platform_view_android.h
FILE: ../../../flutter/shell/platform/android/platform_view_android_delegate/platform_view_android_delegate.cc
FILE: ../../../flutter/shell/platform/android/platform_view_android_delegate/platform_view_android_delegate.h
FILE: ../../../flutter/shell/platform/android/platform_view_android_delegate/platform_view_android_delegate_unittests.cc
FILE: ../../../flutter/shell/platform/android/platform_view_android_jni_impl.cc
FILE: ../../../flutter/shell/platform/android/platform_view_android_jni_impl.h
FILE: ../../../flutter/shell/platform/android/robolectric.properties
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 @@ -64,6 +64,7 @@ shared_library("flutter_shell_native") {
"//flutter/shell/platform/android/context",
"//flutter/shell/platform/android/external_view_embedder",
"//flutter/shell/platform/android/jni",
"//flutter/shell/platform/android/platform_view_android_delegate",
"//flutter/shell/platform/android/surface",
"//flutter/shell/platform/android/surface:native_window",
"//third_party/skia",
Expand Down
145 changes: 6 additions & 139 deletions shell/platform/android/platform_view_android.cc
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,9 @@ PlatformViewAndroid::PlatformViewAndroid(
flutter::TaskRunners task_runners,
std::shared_ptr<PlatformViewAndroidJNI> jni_facade,
bool use_software_rendering)
: PlatformView(delegate, std::move(task_runners)), jni_facade_(jni_facade) {
: PlatformView(delegate, std::move(task_runners)),
jni_facade_(jni_facade),
platform_view_android_delegate_(jni_facade) {
std::shared_ptr<AndroidContext> android_context;
if (use_software_rendering) {
android_context =
Expand Down Expand Up @@ -81,7 +83,8 @@ PlatformViewAndroid::PlatformViewAndroid(
flutter::TaskRunners task_runners,
std::shared_ptr<PlatformViewAndroidJNI> jni_facade)
: PlatformView(delegate, std::move(task_runners)),
jni_facade_(jni_facade) {}
jni_facade_(jni_facade),
platform_view_android_delegate_(jni_facade) {}

PlatformViewAndroid::~PlatformViewAndroid() = default;

Expand Down Expand Up @@ -260,143 +263,7 @@ void PlatformViewAndroid::DispatchSemanticsAction(JNIEnv* env,
void PlatformViewAndroid::UpdateSemantics(
flutter::SemanticsNodeUpdates update,
flutter::CustomAccessibilityActionUpdates actions) {
constexpr size_t kBytesPerNode = 41 * sizeof(int32_t);
constexpr size_t kBytesPerChild = sizeof(int32_t);
constexpr size_t kBytesPerAction = 4 * sizeof(int32_t);

{
size_t num_bytes = 0;
for (const auto& value : update) {
num_bytes += kBytesPerNode;
num_bytes +=
value.second.childrenInTraversalOrder.size() * kBytesPerChild;
num_bytes += value.second.childrenInHitTestOrder.size() * kBytesPerChild;
num_bytes +=
value.second.customAccessibilityActions.size() * kBytesPerChild;
}

// The encoding defined here is used in:
//
// * AccessibilityBridge.java
// * AccessibilityBridgeTest.java
// * accessibility_bridge.mm
//
// If any of the encoding structure or length is changed, those locations
// must be updated (at a minimum).
std::vector<uint8_t> buffer(num_bytes);
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;
for (const auto& value : update) {
// If you edit this code, make sure you update kBytesPerNode
// and/or kBytesPerChild above to match the number of values you are
// sending.
const flutter::SemanticsNode& node = value.second;
buffer_int32[position++] = node.id;
buffer_int32[position++] = node.flags;
buffer_int32[position++] = node.actions;
buffer_int32[position++] = node.maxValueLength;
buffer_int32[position++] = node.currentValueLength;
buffer_int32[position++] = node.textSelectionBase;
buffer_int32[position++] = node.textSelectionExtent;
buffer_int32[position++] = node.platformViewId;
buffer_int32[position++] = node.scrollChildren;
buffer_int32[position++] = node.scrollIndex;
buffer_float32[position++] = (float)node.scrollPosition;
buffer_float32[position++] = (float)node.scrollExtentMax;
buffer_float32[position++] = (float)node.scrollExtentMin;
if (node.label.empty()) {
buffer_int32[position++] = -1;
} else {
buffer_int32[position++] = strings.size();
strings.push_back(node.label);
}
if (node.value.empty()) {
buffer_int32[position++] = -1;
} else {
buffer_int32[position++] = strings.size();
strings.push_back(node.value);
}
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);
}
if (node.hint.empty()) {
buffer_int32[position++] = -1;
} else {
buffer_int32[position++] = strings.size();
strings.push_back(node.hint);
}
buffer_int32[position++] = node.textDirection;
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.getColMajor(&buffer_float32[position]);
position += 16;

buffer_int32[position++] = node.childrenInTraversalOrder.size();
for (int32_t child : node.childrenInTraversalOrder)
buffer_int32[position++] = child;

for (int32_t child : node.childrenInHitTestOrder)
buffer_int32[position++] = child;

buffer_int32[position++] = node.customAccessibilityActions.size();
for (int32_t child : node.customAccessibilityActions)
buffer_int32[position++] = child;
}

// custom accessibility actions.
size_t num_action_bytes = actions.size() * kBytesPerAction;
std::vector<uint8_t> actions_buffer(num_action_bytes);
int32_t* actions_buffer_int32 =
reinterpret_cast<int32_t*>(&actions_buffer[0]);

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.
const flutter::CustomAccessibilityAction& action = value.second;
actions_buffer_int32[actions_position++] = action.id;
actions_buffer_int32[actions_position++] = action.overrideId;
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);
}
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);
}
}

// Calling NewDirectByteBuffer in API level 22 and below with a size of zero
// will cause a JNI crash.
if (actions_buffer.size() > 0) {
jni_facade_->FlutterViewUpdateCustomAccessibilityActions(actions_buffer,
strings);
}

if (buffer.size() > 0) {
jni_facade_->FlutterViewUpdateSemantics(buffer, strings);
}
}
platform_view_android_delegate_.UpdateSemantics(update, actions);
}

void PlatformViewAndroid::RegisterExternalTexture(
Expand Down
3 changes: 3 additions & 0 deletions shell/platform/android/platform_view_android.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "flutter/lib/ui/window/platform_message.h"
#include "flutter/shell/common/platform_view.h"
#include "flutter/shell/platform/android/jni/platform_view_android_jni.h"
#include "flutter/shell/platform/android/platform_view_android_delegate/platform_view_android_delegate.h"
#include "flutter/shell/platform/android/surface/android_native_window.h"
#include "flutter/shell/platform/android/surface/android_surface.h"

Expand Down Expand Up @@ -80,6 +81,8 @@ class PlatformViewAndroid final : public PlatformView {
private:
const std::shared_ptr<PlatformViewAndroidJNI> jni_facade_;

PlatformViewAndroidDelegate platform_view_android_delegate_;

std::unique_ptr<AndroidSurface> android_surface_;
// We use id 0 to mean that no response is expected.
int next_response_id_ = 1;
Expand Down
45 changes: 45 additions & 0 deletions shell/platform/android/platform_view_android_delegate/BUILD.gn
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# 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.

import("//flutter/common/config.gni")
import("//flutter/testing/testing.gni")

source_set("platform_view_android_delegate") {
sources = [
"platform_view_android_delegate.cc",
"platform_view_android_delegate.h",
]

public_configs = [ "//flutter:config" ]

deps = [
"//flutter/common",
"//flutter/fml",
"//flutter/lib/ui",
"//flutter/shell/common",
"//flutter/shell/platform/android/jni",
"//third_party/skia",
]
}

test_fixtures("platform_view_android_delegate_fixtures") {
fixtures = []
}

executable("platform_view_android_delegate_unittests") {
testonly = true

sources = [
"platform_view_android_delegate_unittests.cc",
]

deps = [
":platform_view_android_delegate",
":platform_view_android_delegate_fixtures",
"//flutter/shell/platform/android/jni:jni_mock",
"//flutter/testing",
"//flutter/testing:dart",
"//flutter/third_party/txt",
]
}
Loading

0 comments on commit db8c40b

Please sign in to comment.