Flutter Engine
platform_view_android_delegate.cc
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "flutter/shell/platform/android/platform_view_android_delegate/platform_view_android_delegate.h"
6 
7 namespace flutter {
8 
10  std::shared_ptr<PlatformViewAndroidJNI> jni_facade)
11  : jni_facade_(jni_facade){};
12 
16  constexpr size_t kBytesPerNode = 41 * sizeof(int32_t);
17  constexpr size_t kBytesPerChild = sizeof(int32_t);
18  constexpr size_t kBytesPerAction = 4 * sizeof(int32_t);
19 
20  {
21  size_t num_bytes = 0;
22  for (const auto& value : update) {
23  num_bytes += kBytesPerNode;
24  num_bytes +=
25  value.second.childrenInTraversalOrder.size() * kBytesPerChild;
26  num_bytes += value.second.childrenInHitTestOrder.size() * kBytesPerChild;
27  num_bytes +=
28  value.second.customAccessibilityActions.size() * kBytesPerChild;
29  }
30  // The encoding defined here is used in:
31  //
32  // * AccessibilityBridge.java
33  // * AccessibilityBridgeTest.java
34  // * accessibility_bridge.mm
35  //
36  // If any of the encoding structure or length is changed, those locations
37  // must be updated (at a minimum).
38  std::vector<uint8_t> buffer(num_bytes);
39  int32_t* buffer_int32 = reinterpret_cast<int32_t*>(&buffer[0]);
40  float* buffer_float32 = reinterpret_cast<float*>(&buffer[0]);
41 
42  std::vector<std::string> strings;
43  size_t position = 0;
44  for (const auto& value : update) {
45  // If you edit this code, make sure you update kBytesPerNode
46  // and/or kBytesPerChild above to match the number of values you are
47  // sending.
48  const flutter::SemanticsNode& node = value.second;
49  buffer_int32[position++] = node.id;
50  buffer_int32[position++] = node.flags;
51  buffer_int32[position++] = node.actions;
52  buffer_int32[position++] = node.maxValueLength;
53  buffer_int32[position++] = node.currentValueLength;
54  buffer_int32[position++] = node.textSelectionBase;
55  buffer_int32[position++] = node.textSelectionExtent;
56  buffer_int32[position++] = node.platformViewId;
57  buffer_int32[position++] = node.scrollChildren;
58  buffer_int32[position++] = node.scrollIndex;
59  buffer_float32[position++] = static_cast<float>(node.scrollPosition);
60  buffer_float32[position++] = static_cast<float>(node.scrollExtentMax);
61  buffer_float32[position++] = static_cast<float>(node.scrollExtentMin);
62  if (node.label.empty()) {
63  buffer_int32[position++] = -1;
64  } else {
65  buffer_int32[position++] = strings.size();
66  strings.push_back(node.label);
67  }
68  if (node.value.empty()) {
69  buffer_int32[position++] = -1;
70  } else {
71  buffer_int32[position++] = strings.size();
72  strings.push_back(node.value);
73  }
74  if (node.increasedValue.empty()) {
75  buffer_int32[position++] = -1;
76  } else {
77  buffer_int32[position++] = strings.size();
78  strings.push_back(node.increasedValue);
79  }
80  if (node.decreasedValue.empty()) {
81  buffer_int32[position++] = -1;
82  } else {
83  buffer_int32[position++] = strings.size();
84  strings.push_back(node.decreasedValue);
85  }
86  if (node.hint.empty()) {
87  buffer_int32[position++] = -1;
88  } else {
89  buffer_int32[position++] = strings.size();
90  strings.push_back(node.hint);
91  }
92  buffer_int32[position++] = node.textDirection;
93  buffer_float32[position++] = node.rect.left();
94  buffer_float32[position++] = node.rect.top();
95  buffer_float32[position++] = node.rect.right();
96  buffer_float32[position++] = node.rect.bottom();
97  node.transform.getColMajor(&buffer_float32[position]);
98  position += 16;
99 
100  buffer_int32[position++] = node.childrenInTraversalOrder.size();
101  for (int32_t child : node.childrenInTraversalOrder) {
102  buffer_int32[position++] = child;
103  }
104 
105  for (int32_t child : node.childrenInHitTestOrder) {
106  buffer_int32[position++] = child;
107  }
108 
109  buffer_int32[position++] = node.customAccessibilityActions.size();
110  for (int32_t child : node.customAccessibilityActions) {
111  buffer_int32[position++] = child;
112  }
113  }
114 
115  // custom accessibility actions.
116  size_t num_action_bytes = actions.size() * kBytesPerAction;
117  std::vector<uint8_t> actions_buffer(num_action_bytes);
118  int32_t* actions_buffer_int32 =
119  reinterpret_cast<int32_t*>(&actions_buffer[0]);
120 
121  std::vector<std::string> action_strings;
122  size_t actions_position = 0;
123  for (const auto& value : actions) {
124  // If you edit this code, make sure you update kBytesPerAction
125  // to match the number of values you are
126  // sending.
128  actions_buffer_int32[actions_position++] = action.id;
129  actions_buffer_int32[actions_position++] = action.overrideId;
130  if (action.label.empty()) {
131  actions_buffer_int32[actions_position++] = -1;
132  } else {
133  actions_buffer_int32[actions_position++] = action_strings.size();
134  action_strings.push_back(action.label);
135  }
136  if (action.hint.empty()) {
137  actions_buffer_int32[actions_position++] = -1;
138  } else {
139  actions_buffer_int32[actions_position++] = action_strings.size();
140  action_strings.push_back(action.hint);
141  }
142  }
143 
144  // Calling NewDirectByteBuffer in API level 22 and below with a size of zero
145  // will cause a JNI crash.
146  if (actions_buffer.size() > 0) {
147  jni_facade_->FlutterViewUpdateCustomAccessibilityActions(actions_buffer,
148  action_strings);
149  }
150 
151  if (buffer.size() > 0) {
152  jni_facade_->FlutterViewUpdateSemantics(buffer, strings);
153  }
154  }
155 }
156 
157 } // namespace flutter
std::vector< int32_t > childrenInHitTestOrder
std::vector< int32_t > customAccessibilityActions
std::unordered_map< int32_t, SemanticsNode > SemanticsNodeUpdates
std::vector< int32_t > childrenInTraversalOrder
uint8_t value
PlatformViewAndroidDelegate(std::shared_ptr< PlatformViewAndroidJNI > jni_facade)
SemanticsAction action
std::unordered_map< int32_t, CustomAccessibilityAction > CustomAccessibilityActionUpdates
void UpdateSemantics(flutter::SemanticsNodeUpdates update, flutter::CustomAccessibilityActionUpdates actions)