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  const StringAttributes& attributes,
11  int32_t* buffer_int32,
12  size_t& position,
13  std::vector<std::vector<uint8_t>>& string_attribute_args) {
14  if (attributes.empty()) {
15  buffer_int32[position++] = -1;
16  return;
17  }
18  buffer_int32[position++] = attributes.size();
19  for (const auto& attribute : attributes) {
20  buffer_int32[position++] = attribute->start;
21  buffer_int32[position++] = attribute->end;
22  buffer_int32[position++] = static_cast<int32_t>(attribute->type);
23  switch (attribute->type) {
25  buffer_int32[position++] = -1;
26  break;
28  buffer_int32[position++] = string_attribute_args.size();
29  std::shared_ptr<LocaleStringAttribute> locale_attribute =
30  std::static_pointer_cast<LocaleStringAttribute>(attribute);
31  string_attribute_args.push_back(
32  {locale_attribute->locale.begin(), locale_attribute->locale.end()});
33  break;
34  }
35  }
36 }
37 
39  std::shared_ptr<PlatformViewAndroidJNI> jni_facade)
40  : jni_facade_(jni_facade){};
41 
45  constexpr size_t kBytesPerNode = 47 * sizeof(int32_t);
46  constexpr size_t kBytesPerChild = sizeof(int32_t);
47  constexpr size_t kBytesPerCustomAction = sizeof(int32_t);
48  constexpr size_t kBytesPerAction = 4 * sizeof(int32_t);
49  constexpr size_t kBytesPerStringAttribute = 4 * sizeof(int32_t);
50 
51  {
52  size_t num_bytes = 0;
53  for (const auto& value : update) {
54  num_bytes += kBytesPerNode;
55  num_bytes +=
56  value.second.childrenInTraversalOrder.size() * kBytesPerChild;
57  num_bytes += value.second.childrenInHitTestOrder.size() * kBytesPerChild;
58  num_bytes += value.second.customAccessibilityActions.size() *
59  kBytesPerCustomAction;
60  num_bytes +=
61  value.second.labelAttributes.size() * kBytesPerStringAttribute;
62  num_bytes +=
63  value.second.valueAttributes.size() * kBytesPerStringAttribute;
64  num_bytes += value.second.increasedValueAttributes.size() *
65  kBytesPerStringAttribute;
66  num_bytes += value.second.decreasedValueAttributes.size() *
67  kBytesPerStringAttribute;
68  num_bytes +=
69  value.second.hintAttributes.size() * kBytesPerStringAttribute;
70  }
71  // The encoding defined here is used in:
72  //
73  // * AccessibilityBridge.java
74  // * AccessibilityBridgeTest.java
75  // * accessibility_bridge.mm
76  //
77  // If any of the encoding structure or length is changed, those locations
78  // must be updated (at a minimum).
79  std::vector<uint8_t> buffer(num_bytes);
80  int32_t* buffer_int32 = reinterpret_cast<int32_t*>(&buffer[0]);
81  float* buffer_float32 = reinterpret_cast<float*>(&buffer[0]);
82 
83  std::vector<std::string> strings;
84  std::vector<std::vector<uint8_t>> string_attribute_args;
85  size_t position = 0;
86  for (const auto& value : update) {
87  // If you edit this code, make sure you update kBytesPerNode
88  // and/or kBytesPerChild above to match the number of values you are
89  // sending.
90  const flutter::SemanticsNode& node = value.second;
91  buffer_int32[position++] = node.id;
92  buffer_int32[position++] = node.flags;
93  buffer_int32[position++] = node.actions;
94  buffer_int32[position++] = node.maxValueLength;
95  buffer_int32[position++] = node.currentValueLength;
96  buffer_int32[position++] = node.textSelectionBase;
97  buffer_int32[position++] = node.textSelectionExtent;
98  buffer_int32[position++] = node.platformViewId;
99  buffer_int32[position++] = node.scrollChildren;
100  buffer_int32[position++] = node.scrollIndex;
101  buffer_float32[position++] = static_cast<float>(node.scrollPosition);
102  buffer_float32[position++] = static_cast<float>(node.scrollExtentMax);
103  buffer_float32[position++] = static_cast<float>(node.scrollExtentMin);
104  if (node.label.empty()) {
105  buffer_int32[position++] = -1;
106  } else {
107  buffer_int32[position++] = strings.size();
108  strings.push_back(node.label);
109  }
110 
112  position, string_attribute_args);
113  if (node.value.empty()) {
114  buffer_int32[position++] = -1;
115  } else {
116  buffer_int32[position++] = strings.size();
117  strings.push_back(node.value);
118  }
119 
121  position, string_attribute_args);
122  if (node.increasedValue.empty()) {
123  buffer_int32[position++] = -1;
124  } else {
125  buffer_int32[position++] = strings.size();
126  strings.push_back(node.increasedValue);
127  }
128 
130  position, string_attribute_args);
131  if (node.decreasedValue.empty()) {
132  buffer_int32[position++] = -1;
133  } else {
134  buffer_int32[position++] = strings.size();
135  strings.push_back(node.decreasedValue);
136  }
137 
139  position, string_attribute_args);
140 
141  if (node.hint.empty()) {
142  buffer_int32[position++] = -1;
143  } else {
144  buffer_int32[position++] = strings.size();
145  strings.push_back(node.hint);
146  }
147 
148  putStringAttributesIntoBuffer(node.hintAttributes, buffer_int32, position,
149  string_attribute_args);
150 
151  if (node.tooltip.empty()) {
152  buffer_int32[position++] = -1;
153  } else {
154  buffer_int32[position++] = strings.size();
155  strings.push_back(node.tooltip);
156  }
157 
158  buffer_int32[position++] = node.textDirection;
159  buffer_float32[position++] = node.rect.left();
160  buffer_float32[position++] = node.rect.top();
161  buffer_float32[position++] = node.rect.right();
162  buffer_float32[position++] = node.rect.bottom();
163  node.transform.getColMajor(&buffer_float32[position]);
164  position += 16;
165 
166  buffer_int32[position++] = node.childrenInTraversalOrder.size();
167  for (int32_t child : node.childrenInTraversalOrder) {
168  buffer_int32[position++] = child;
169  }
170 
171  for (int32_t child : node.childrenInHitTestOrder) {
172  buffer_int32[position++] = child;
173  }
174 
175  buffer_int32[position++] = node.customAccessibilityActions.size();
176  for (int32_t child : node.customAccessibilityActions) {
177  buffer_int32[position++] = child;
178  }
179  }
180 
181  // custom accessibility actions.
182  size_t num_action_bytes = actions.size() * kBytesPerAction;
183  std::vector<uint8_t> actions_buffer(num_action_bytes);
184  int32_t* actions_buffer_int32 =
185  reinterpret_cast<int32_t*>(&actions_buffer[0]);
186 
187  std::vector<std::string> action_strings;
188  size_t actions_position = 0;
189  for (const auto& value : actions) {
190  // If you edit this code, make sure you update kBytesPerAction
191  // to match the number of values you are
192  // sending.
194  actions_buffer_int32[actions_position++] = action.id;
195  actions_buffer_int32[actions_position++] = action.overrideId;
196  if (action.label.empty()) {
197  actions_buffer_int32[actions_position++] = -1;
198  } else {
199  actions_buffer_int32[actions_position++] = action_strings.size();
200  action_strings.push_back(action.label);
201  }
202  if (action.hint.empty()) {
203  actions_buffer_int32[actions_position++] = -1;
204  } else {
205  actions_buffer_int32[actions_position++] = action_strings.size();
206  action_strings.push_back(action.hint);
207  }
208  }
209 
210  // Calling NewDirectByteBuffer in API level 22 and below with a size of zero
211  // will cause a JNI crash.
212  if (actions_buffer.size() > 0) {
213  jni_facade_->FlutterViewUpdateCustomAccessibilityActions(actions_buffer,
214  action_strings);
215  }
216 
217  if (buffer.size() > 0) {
218  jni_facade_->FlutterViewUpdateSemantics(buffer, strings,
219  string_attribute_args);
220  }
221  }
222 }
223 
224 } // namespace flutter
StringAttributes increasedValueAttributes
std::vector< int32_t > childrenInHitTestOrder
StringAttributes decreasedValueAttributes
std::vector< int32_t > customAccessibilityActions
std::unordered_map< int32_t, SemanticsNode > SemanticsNodeUpdates
std::vector< int32_t > childrenInTraversalOrder
std::vector< StringAttributePtr > StringAttributes
uint8_t value
StringAttributes valueAttributes
const FlutterSemanticsNode * node
Definition: fl_view.cc:83
PlatformViewAndroidDelegate(std::shared_ptr< PlatformViewAndroidJNI > jni_facade)
SemanticsAction action
StringAttributes hintAttributes
static const uint8_t buffer[]
void putStringAttributesIntoBuffer(const StringAttributes &attributes, int32_t *buffer_int32, size_t &position, std::vector< std::vector< uint8_t >> &string_attribute_args)
StringAttributes labelAttributes
std::unordered_map< int32_t, CustomAccessibilityAction > CustomAccessibilityActionUpdates
void UpdateSemantics(flutter::SemanticsNodeUpdates update, flutter::CustomAccessibilityActionUpdates actions)