Flutter Engine
The Flutter Engine
accessibility_bridge.h
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#ifndef FLUTTER_SHELL_PLATFORM_FUCHSIA_FLUTTER_ACCESSIBILITY_BRIDGE_H_
6#define FLUTTER_SHELL_PLATFORM_FUCHSIA_FLUTTER_ACCESSIBILITY_BRIDGE_H_
7
8// Work around symbol conflicts with ICU.
9#undef TRUE
10#undef FALSE
11
12#include <fuchsia/accessibility/semantics/cpp/fidl.h>
13#include <fuchsia/ui/gfx/cpp/fidl.h>
14#include <lib/fidl/cpp/binding_set.h>
15#include <lib/inspect/component/cpp/component.h>
16#include <zircon/types.h>
17
18#include <memory>
19#include <optional>
20#include <queue>
21#include <unordered_map>
22#include <unordered_set>
23#include <vector>
24
25#include "flutter/fml/macros.h"
26#include "flutter/lib/ui/semantics/semantics_node.h"
27
28namespace flutter_runner {
29
30// Accessibility bridge.
31//
32// This class intermediates accessibility-related calls between Fuchsia and
33// Flutter. It serves to resolve the impedance mismatch between Flutter's
34// platform-agnostic accessibility APIs and Fuchsia's APIs and behaviour.
35//
36// This bridge performs the following functions, among others:
37//
38// * Translates Flutter's semantics node updates to events Fuchsia requires
39// (e.g. Flutter only sends updates for changed nodes, but Fuchsia requires
40// the entire flattened subtree to be sent when a node changes.
42 : public fuchsia::accessibility::semantics::SemanticListener {
43 public:
47
48 // TODO(MI4-2531, FIDL-718): Remove this. We shouldn't be worried about
49 // batching messages at this level.
50 // FIDL may encode a C++ struct as larger than the sizeof the C++ struct.
51 // This is to make sure we don't send updates that are too large.
52 static constexpr uint32_t kMaxMessageSize = ZX_CHANNEL_MAX_MSG_BYTES / 2;
53
54 static_assert(fuchsia::accessibility::semantics::MAX_LABEL_SIZE <
55 kMaxMessageSize - 1);
56
57 // Flutter uses signed 32 bit integers for node IDs, while Fuchsia uses
58 // unsigned 32 bit integers. A change in the size on either one would break
59 // casts and size tracking logic in the implementation.
60 static constexpr size_t kNodeIdSize = sizeof(flutter::SemanticsNode::id);
61 static_assert(
63 sizeof(fuchsia::accessibility::semantics::Node().node_id()),
64 "flutter::SemanticsNode::id and "
65 "fuchsia::accessibility::semantics::Node::node_id differ in size.");
66
67 // Maximum number of node ids to be deleted through the Semantics API.
68 static constexpr size_t kMaxDeletionsPerUpdate =
70
72 SetSemanticsEnabledCallback set_semantics_enabled_callback,
73 DispatchSemanticsActionCallback dispatch_semantics_action_callback,
74 fuchsia::accessibility::semantics::SemanticsManagerHandle
75 semantics_manager,
76 fuchsia::ui::views::ViewRef view_ref,
77 inspect::Node inspect_node);
78
79 // Returns true if accessible navigation is enabled.
80 bool GetSemanticsEnabled() const;
81
82 // Enables Flutter accessibility navigation features.
83 //
84 // Once enabled, any semantics updates in the Flutter application will
85 // trigger |FuchsiaAccessibility::DispatchAccessibilityEvent| callbacks
86 // to send events back to the Fuchsia SemanticsManager.
87 void SetSemanticsEnabled(bool enabled);
88
89 // Adds a semantics node update to the buffer of node updates to apply.
91 float view_pixel_ratio);
92
93 // Requests a message announcement from the accessibility TTS system.
94 void RequestAnnounce(const std::string message);
95
96 // Notifies the bridge of a 'hover move' touch exploration event.
97 zx_status_t OnHoverMove(double x, double y);
98
99 // |fuchsia::accessibility::semantics::SemanticListener|
100 void HitTest(
101 fuchsia::math::PointF local_point,
102 fuchsia::accessibility::semantics::SemanticListener::HitTestCallback
103 callback) override;
104
105 // |fuchsia::accessibility::semantics::SemanticListener|
107 uint32_t node_id,
109 fuchsia::accessibility::semantics::SemanticListener::
110 OnAccessibilityActionRequestedCallback callback) override;
111
112 private:
113 // Fuchsia's default root semantic node id.
114 static constexpr int32_t kRootNodeId = 0;
115
116 // Represents an atomic semantic update to Fuchsia, which can contain deletes
117 // and updates of semantic nodes.
118 //
119 // An atomic update is a set of operations that take a semantic tree in a
120 // valid state to another valid state. Please check the semantics FIDL
121 // documentation for details.
122 struct FuchsiaAtomicUpdate {
123 FuchsiaAtomicUpdate() = default;
124 ~FuchsiaAtomicUpdate() = default;
125 FuchsiaAtomicUpdate(FuchsiaAtomicUpdate&&) = default;
126
127 // Adds a node to be updated. |size| contains the
128 // size in bytes of the node to be updated.
129 void AddNodeUpdate(fuchsia::accessibility::semantics::Node node,
130 size_t size);
131
132 // Adds a node to be deleted.
133 void AddNodeDeletion(uint32_t id);
134
135 std::vector<std::pair<fuchsia::accessibility::semantics::Node, size_t>>
136 updates;
137 std::vector<uint32_t> deletions;
138 };
139
140 // Holds a flutter semantic node and some extra info.
141 // In particular, it adds a screen_rect field to flutter::SemanticsNode.
142 struct SemanticsNode {
144 SkRect screen_rect;
145 };
146
147 fuchsia::accessibility::semantics::Node GetRootNodeUpdate(size_t& node_size);
148
149 // Derives the BoundingBox of a Flutter semantics node from its
150 // rect and elevation.
151 fuchsia::ui::gfx::BoundingBox GetNodeLocation(
152 const flutter::SemanticsNode& node) const;
153
154 // Gets mat4 transformation from a Flutter semantics node.
155 fuchsia::ui::gfx::mat4 GetNodeTransform(
156 const flutter::SemanticsNode& node) const;
157
158 // Converts a Flutter semantics node's transformation to a mat4.
159 fuchsia::ui::gfx::mat4 ConvertSkiaTransformToMat4(
160 const SkM44 transform) const;
161
162 // Derives the attributes for a Fuchsia semantics node from a Flutter
163 // semantics node.
164 fuchsia::accessibility::semantics::Attributes GetNodeAttributes(
165 const flutter::SemanticsNode& node,
166 size_t* added_size) const;
167
168 // Derives the states for a Fuchsia semantics node from a Flutter semantics
169 // node.
170 fuchsia::accessibility::semantics::States GetNodeStates(
171 const flutter::SemanticsNode& node,
172 size_t* additional_size) const;
173
174 // Derives the set of supported actions for a Fuchsia semantics node from
175 // a Flutter semantics node.
176 std::vector<fuchsia::accessibility::semantics::Action> GetNodeActions(
177 const flutter::SemanticsNode& node,
178 size_t* additional_size) const;
179
180 // Derives the role for a Fuchsia semantics node from a Flutter
181 // semantics node.
183 const flutter::SemanticsNode& node) const;
184
185 // Gets the set of reachable descendants from the given node id.
186 std::unordered_set<int32_t> GetDescendants(int32_t node_id) const;
187
188 // Removes internal references to any dangling nodes from previous
189 // updates, and adds the nodes to be deleted to the current |atomic_update|.
190 //
191 // The node ids to be deleted are only collected at this point, and will be
192 // committed in the next call to |Apply()|.
193 void PruneUnreachableNodes(FuchsiaAtomicUpdate* atomic_update);
194
195 // Updates the on-screen positions of accessibility elements,
196 // starting from the root element with an identity matrix.
197 //
198 // This should be called from Update.
199 void UpdateScreenRects();
200
201 // Updates the on-screen positions of accessibility elements, starting
202 // from node_id and using the specified transform.
203 //
204 // Update calls this via UpdateScreenRects().
205 void UpdateScreenRects(int32_t node_id,
206 SkM44 parent_transform,
207 std::unordered_set<int32_t>* visited_nodes);
208
209 // Traverses the semantics tree to find the node_id hit by the given x,y
210 // point.
211 //
212 // Assumes that SemanticsNode::screen_rect is up to date.
213 std::optional<int32_t> GetHitNode(int32_t node_id, float x, float y);
214
215 // Returns whether the node is considered focusable.
216 bool IsFocusable(const flutter::SemanticsNode& node) const;
217
218 // Converts a fuchsia::accessibility::semantics::Action to a
219 // flutter::SemanticsAction.
220 //
221 // The node_id parameter is used for printing warnings about unsupported
222 // action types.
223 std::optional<flutter::SemanticsAction> GetFlutterSemanticsAction(
225 uint32_t node_id);
226
227 // Applies the updates and deletions in |atomic_update|, sending them via
228 // |tree_ptr|.
229 void Apply(FuchsiaAtomicUpdate* atomic_update);
230
231 // |fuchsia::accessibility::semantics::SemanticListener|
232 void OnSemanticsModeChanged(bool enabled,
233 OnSemanticsModeChangedCallback callback) override;
234
235#if !FLUTTER_RELEASE
236 // Fills the inspect tree with debug information about the semantic tree.
237 void FillInspectTree(int32_t flutter_node_id,
238 int32_t current_level,
239 inspect::Node inspect_node,
240 inspect::Inspector* inspector) const;
241#endif // !FLUTTER_RELEASE
242
243 SetSemanticsEnabledCallback set_semantics_enabled_callback_;
244 DispatchSemanticsActionCallback dispatch_semantics_action_callback_;
245 flutter::SemanticsNode root_flutter_semantics_node_;
246 float last_seen_view_pixel_ratio_ = 1.f;
247
248 fidl::Binding<fuchsia::accessibility::semantics::SemanticListener> binding_;
249 fuchsia::accessibility::semantics::SemanticsManagerPtr
250 fuchsia_semantics_manager_;
251 fuchsia::accessibility::semantics::SemanticTreePtr tree_ptr_;
252
253 // This is the cache of all nodes we've sent to Fuchsia's SemanticsManager.
254 // Assists with pruning unreachable nodes and hit testing.
255 std::unordered_map<int32_t, SemanticsNode> nodes_;
256 bool semantics_enabled_;
257
258 // Queue of atomic updates to be sent to Fuchsia.
259 std::shared_ptr<std::queue<FuchsiaAtomicUpdate>> atomic_updates_;
260
261 // Node to publish inspect data.
262 inspect::Node inspect_node_;
263
264#if !FLUTTER_RELEASE
265 // Inspect node to store a dump of the semantic tree. Note that this only gets
266 // computed if requested, so it does not use memory to store the dump unless
267 // an explicit request is made.
268 inspect::LazyNode inspect_node_tree_dump_;
269#endif // !FLUTTER_RELEASE
270
271 FML_DISALLOW_COPY_AND_ASSIGN(AccessibilityBridge);
272};
273} // namespace flutter_runner
274
275#endif // FLUTTER_SHELL_PLATFORM_FUCHSIA_FLUTTER_ACCESSIBILITY_BRIDGE_H_
Definition: SkM44.h:150
void AddSemanticsNodeUpdate(const flutter::SemanticsNodeUpdates update, float view_pixel_ratio)
std::function< void(bool)> SetSemanticsEnabledCallback
void OnAccessibilityActionRequested(uint32_t node_id, fuchsia::accessibility::semantics::Action action, fuchsia::accessibility::semantics::SemanticListener::OnAccessibilityActionRequestedCallback callback) override
void HitTest(fuchsia::math::PointF local_point, fuchsia::accessibility::semantics::SemanticListener::HitTestCallback callback) override
static constexpr uint32_t kMaxMessageSize
void RequestAnnounce(const std::string message)
std::function< void(int32_t, flutter::SemanticsAction)> DispatchSemanticsActionCallback
AccessibilityBridge(SetSemanticsEnabledCallback set_semantics_enabled_callback, DispatchSemanticsActionCallback dispatch_semantics_action_callback, fuchsia::accessibility::semantics::SemanticsManagerHandle semantics_manager, fuchsia::ui::views::ViewRef view_ref, inspect::Node inspect_node)
zx_status_t OnHoverMove(double x, double y)
static constexpr size_t kMaxDeletionsPerUpdate
FlKeyEvent uint64_t FlKeyResponderAsyncCallback callback
Dart_NativeFunction function
Definition: fuchsia.cc:51
Win32Message message
double y
double x
std::unordered_map< int32_t, SemanticsNode > SemanticsNodeUpdates
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition: switches.h:259
Definition: update.py:1
static SkColor4f transform(SkColor4f c, SkColorSpace *src, SkColorSpace *dst)
Definition: p3.cpp:47
std::shared_ptr< const fml::Mapping > data
Definition: texture_gles.cc:63