Flutter Engine
pointer_data_dispatcher.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 POINTER_DATA_DISPATCHER_H_
6 #define POINTER_DATA_DISPATCHER_H_
7 
8 #include "flutter/runtime/runtime_controller.h"
9 #include "flutter/shell/common/animator.h"
10 
11 namespace flutter {
12 
13 class PointerDataDispatcher;
14 
15 //------------------------------------------------------------------------------
16 /// The `Engine` pointer data dispatcher that forwards the packet received from
17 /// `PlatformView::DispatchPointerDataPacket` on the platform thread, to
18 /// `Window::DispatchPointerDataPacket` on the UI thread.
19 ///
20 /// This class is used to filter the packets so the Flutter framework on the UI
21 /// thread will receive packets with some desired properties. See
22 /// `SmoothPointerDataDispatcher` for an example which filters irregularly
23 /// delivered packets, and dispatches them in sync with the VSYNC signal.
24 ///
25 /// This object will be owned by the engine because it relies on the engine's
26 /// `Animator` (which owns `VsyncWaiter`) and `RuntimeController` to do the
27 /// filtering. This object is currently designed to be only called from the UI
28 /// thread (no thread safety is guaranteed).
29 ///
30 /// The `PlatformView` decides which subclass of `PointerDataDispatcher` is
31 /// constructed by sending a `PointerDataDispatcherMaker` to the engine's
32 /// constructor in `Shell::CreateShellOnPlatformThread`. This is needed because:
33 /// (1) Different platforms (e.g., Android, iOS) have different dispatchers
34 /// so the decision has to be made per `PlatformView`.
35 /// (2) The `PlatformView` can only be accessed from the PlatformThread while
36 /// this class (as owned by engine) can only be accessed in the UI thread.
37 /// Hence `PlatformView` creates a `PointerDataDispatchMaker` on the
38 /// platform thread, and sends it to the UI thread for the final
39 /// construction of the `PointerDataDispatcher`.
41  public:
42  /// The interface for Engine to implement.
43  class Delegate {
44  public:
45  /// Actually dispatch the packet using Engine's `animator_` and
46  /// `runtime_controller_`.
47  virtual void DoDispatchPacket(std::unique_ptr<PointerDataPacket> packet,
48  uint64_t trace_flow_id) = 0;
49 
50  //--------------------------------------------------------------------------
51  /// @brief Schedule a secondary callback to be executed right after the
52  /// main `VsyncWaiter::AsyncWaitForVsync` callback (which is added
53  /// by `Animator::RequestFrame`).
54  ///
55  /// Like the callback in `AsyncWaitForVsync`, this callback is
56  /// only scheduled to be called once per |id|, and it will be
57  /// called in the UI thread. If there is no AsyncWaitForVsync
58  /// callback (`Animator::RequestFrame` is not called), this
59  /// secondary callback will still be executed at vsync.
60  ///
61  /// This callback is used to provide the vsync signal needed by
62  /// `SmoothPointerDataDispatcher`, and for `Animator` input flow
63  /// events.
64  virtual void ScheduleSecondaryVsyncCallback(
65  uintptr_t id,
66  const fml::closure& callback) = 0;
67  };
68 
69  //----------------------------------------------------------------------------
70  /// @brief Signal that `PlatformView` has a packet to be dispatched.
71  ///
72  /// @param[in] packet The `PointerDataPacket` to be dispatched.
73  /// @param[in] trace_flow_id The id for `Animator::EnqueueTraceFlowId`.
74  virtual void DispatchPacket(std::unique_ptr<PointerDataPacket> packet,
75  uint64_t trace_flow_id) = 0;
76 
77  //----------------------------------------------------------------------------
78  /// @brief Default destructor.
79  virtual ~PointerDataDispatcher();
80 };
81 
82 //------------------------------------------------------------------------------
83 /// The default dispatcher that forwards the packet without any modification.
84 ///
86  public:
87  DefaultPointerDataDispatcher(Delegate& delegate) : delegate_(delegate) {}
88 
89  // |PointerDataDispatcer|
90  void DispatchPacket(std::unique_ptr<PointerDataPacket> packet,
91  uint64_t trace_flow_id) override;
92 
94 
95  protected:
96  Delegate& delegate_;
97 
99 };
100 
101 //------------------------------------------------------------------------------
102 /// A dispatcher that may temporarily store and defer the last received
103 /// PointerDataPacket if multiple packets are received in one VSYNC. The
104 /// deferred packet will be sent in the next vsync in order to smooth out the
105 /// events. This filters out irregular input events delivery to provide a smooth
106 /// scroll on iPhone X/Xs.
107 ///
108 /// It works as follows:
109 ///
110 /// When `DispatchPacket` is called while a preivous pointer data dispatch is
111 /// still in progress (its frame isn't finished yet), it means that an input
112 /// event is delivered to us too fast. That potentially means a later event will
113 /// be too late which could cause the missing of a frame. Hence we'll cache it
114 /// in `pending_packet_` for the next frame to smooth it out.
115 ///
116 /// If the input event is sent to us regularly at the same rate of VSYNC (say
117 /// at 60Hz), this would be identical to `DefaultPointerDataDispatcher` where
118 /// `runtime_controller_->DispatchPointerDataPacket` is always called right
119 /// away. That's because `is_pointer_data_in_progress_` will always be false
120 /// when `DispatchPacket` is called since it will be cleared by the end of a
121 /// frame through `ScheduleSecondaryVsyncCallback`. This is the case for all
122 /// Android/iOS devices before iPhone X/XS.
123 ///
124 /// If the input event is irregular, but with a random latency of no more than
125 /// one frame, this would guarantee that we'll miss at most 1 frame. Without
126 /// this, we could miss half of the frames.
127 ///
128 /// If the input event is delivered at a higher rate than that of VSYNC, this
129 /// would at most add a latency of one event delivery. For example, if the
130 /// input event is delivered at 120Hz (this is only true for iPad pro, not even
131 /// iPhone X), this may delay the handling of an input event by 8ms.
132 ///
133 /// The assumption of this solution is that the sampling itself is still
134 /// regular. Only the event delivery is allowed to be irregular. So far this
135 /// assumption seems to hold on all devices. If it's changed in the future,
136 /// we'll need a different solution.
137 ///
138 /// See also input_events_unittests.cc where we test all our claims above.
140  public:
142 
143  // |PointerDataDispatcer|
144  void DispatchPacket(std::unique_ptr<PointerDataPacket> packet,
145  uint64_t trace_flow_id) override;
146 
147  virtual ~SmoothPointerDataDispatcher();
148 
149  private:
150  // If non-null, this will be a pending pointer data packet for the next frame
151  // to consume. This is used to smooth out the irregular drag events delivery.
152  // See also `DispatchPointerDataPacket` and input_events_unittests.cc.
153  std::unique_ptr<PointerDataPacket> pending_packet_;
154  int pending_trace_flow_id_ = -1;
155 
156  bool is_pointer_data_in_progress_ = false;
157 
159 
160  void DispatchPendingPacket();
161 
163 
165 };
166 
167 //--------------------------------------------------------------------------
168 /// @brief Signature for constructing PointerDataDispatcher.
169 ///
170 /// @param[in] delegate the `Flutter::Engine`
171 ///
173  std::function<std::unique_ptr<PointerDataDispatcher>(
175 
176 } // namespace flutter
177 
178 #endif // POINTER_DATA_DISPATCHER_H_
MockDelegate delegate_
The interface for Engine to implement.
std::function< std::unique_ptr< PointerDataDispatcher >(PointerDataDispatcher::Delegate &)> PointerDataDispatcherMaker
Signature for constructing PointerDataDispatcher.
FlKeyEvent FlKeyResponderAsyncCallback callback
std::function< void()> closure
Definition: closure.h:14
virtual ~PointerDataDispatcher()
Default destructor.
virtual void DispatchPacket(std::unique_ptr< PointerDataPacket > packet, uint64_t trace_flow_id)=0
Signal that PlatformView has a packet to be dispatched.
virtual void ScheduleSecondaryVsyncCallback(uintptr_t id, const fml::closure &callback)=0
Schedule a secondary callback to be executed right after the main VsyncWaiter::AsyncWaitForVsync call...
virtual void DoDispatchPacket(std::unique_ptr< PointerDataPacket > packet, uint64_t trace_flow_id)=0
#define FML_DISALLOW_COPY_AND_ASSIGN(TypeName)
Definition: macros.h:27