text: // 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.
  
  #ifndef COMMON_PLATFORM_VIEW_H_
  #define COMMON_PLATFORM_VIEW_H_
  
  #include <functional>
  #include <memory>
  
  #include "flutter/common/graphics/texture.h"
  #include "flutter/common/task_runners.h"
  #include "flutter/flow/embedded_views.h"
  #include "flutter/flow/surface.h"
  #include "flutter/fml/macros.h"
  #include "flutter/fml/mapping.h"
  #include "flutter/fml/memory/weak_ptr.h"
  #include "flutter/lib/ui/semantics/custom_accessibility_action.h"
  #include "flutter/lib/ui/semantics/semantics_node.h"
  #include "flutter/lib/ui/window/key_data_packet.h"
  #include "flutter/lib/ui/window/platform_message.h"
  #include "flutter/lib/ui/window/pointer_data_packet.h"
  #include "flutter/lib/ui/window/pointer_data_packet_converter.h"
  #include "flutter/lib/ui/window/viewport_metrics.h"
  #include "flutter/shell/common/platform_message_handler.h"
  #include "flutter/shell/common/pointer_data_dispatcher.h"
  #include "flutter/shell/common/vsync_waiter.h"
  #include "third_party/skia/include/gpu/GrDirectContext.h"
  
  namespace flutter {
  
  //------------------------------------------------------------------------------
  /// @brief      Platform views are created by the shell on the platform task
  ///             runner. Unless explicitly specified, all platform view methods
  ///             are called on the platform task runner as well. Platform views
  ///             are usually sub-classed on a per platform basis and the bulk of
  ///             the window system integration happens using that subclass. Since
  ///             most platform window toolkits are usually only safe to access on
  ///             a single "main" thread, any interaction that requires access to
  ///             the underlying platform's window toolkit is routed through the
  ///             platform view associated with that shell. This involves
  ///             operations like settings up and tearing down the render surface,
  ///             platform messages, interacting with accessibility features on
  ///             the platform, input events, etc.
  ///
  class PlatformView {
   public:
    //----------------------------------------------------------------------------
    /// @brief      Used to forward events from the platform view to interested
    ///             subsystems. This forwarding is done by the shell which sets
    ///             itself up as the delegate of the platform view.
    ///
    class Delegate {
     public:
      using KeyDataResponse = std::function<void(bool)>;
      //--------------------------------------------------------------------------
      /// @brief      Notifies the delegate that the platform view was created
      ///             with the given render surface. This surface is platform
      ///             (iOS, Android) and client-rendering API (OpenGL, Software,
      ///             Metal, Vulkan) specific. This is usually a sign to the
      ///             rasterizer to set up and begin rendering to that surface.
      ///
      /// @param[in]  surface           The surface
      ///
      virtual void OnPlatformViewCreated(std::unique_ptr<Surface> surface) = 0;
  
      //--------------------------------------------------------------------------
      /// @brief      Notifies the delegate that the platform view was destroyed.
      ///             This is usually a sign to the rasterizer to suspend
      ///             rendering a previously configured surface and collect any
      ///             intermediate resources.
      ///
      virtual void OnPlatformViewDestroyed() = 0;
  
      //--------------------------------------------------------------------------
      /// @brief      Notifies the delegate that the specified callback needs to
      ///             be invoked after the rasterizer is done rendering the next
      ///             frame. This callback will be called on the render thread and
      ///             it is caller responsibility to perform any re-threading as
      ///             necessary. Due to the asynchronous nature of rendering in
      ///             Flutter, embedders usually add a placeholder over the
      ///             contents in which Flutter is going to render when Flutter is
      ///             first initialized. This callback may be used as a signal to
      ///             remove that placeholder.
      ///
      /// @attention  The callback will be invoked on the render thread and not
      ///             the calling thread.
      ///
      /// @param[in]  closure  The callback to execute on the next frame.
      ///
      virtual void OnPlatformViewSetNextFrameCallback(
          const fml::closure& closure) = 0;
  
      //--------------------------------------------------------------------------
      /// @brief      Notifies the delegate the viewport metrics of the platform
      ///             view have been updated. The rasterizer will need to be
      ///             reconfigured to render the frame in the updated viewport
      ///             metrics.
      ///
      /// @param[in]  metrics  The updated viewport metrics.
      ///
      virtual void OnPlatformViewSetViewportMetrics(
          const ViewportMetrics& metrics) = 0;
  
      //--------------------------------------------------------------------------
      /// @brief      Notifies the delegate that the platform has dispatched a
      ///             platform message from the embedder to the Flutter
      ///             application. This message must be forwarded to the running
      ///             isolate hosted by the engine on the UI thread.
      ///
      /// @param[in]  message  The platform message to dispatch to the running
      ///                      root isolate.
      ///
      virtual void OnPlatformViewDispatchPlatformMessage(
          std::unique_ptr<PlatformMessage> message) = 0;
  
      //--------------------------------------------------------------------------
      /// @brief      Notifies the delegate that the platform view has encountered
      ///             a pointer event. This pointer event needs to be forwarded to
      ///             the running root isolate hosted by the engine on the UI
      ///             thread.
      ///
      /// @param[in]  packet  The pointer data packet containing multiple pointer
      ///                     events.
      ///
      virtual void OnPlatformViewDispatchPointerDataPacket(
          std::unique_ptr<PointerDataPacket> packet) = 0;
  
      //--------------------------------------------------------------------------
      /// @brief      Notifies the delegate that the platform view has encountered
      ///             an accessibility related action on the specified node. This
      ///             event must be forwarded to the running root isolate hosted
      ///             by the engine on the UI thread.
      ///
      /// @param[in]  id      The identifier of the accessibility node.
      /// @param[in]  action  The accessibility related action performed on the
      ///                     node of the specified ID.
      /// @param[in]  args    An optional list of argument that apply to the
      ///                     specified action.
      ///
      virtual void OnPlatformViewDispatchSemanticsAction(
          int32_t id,
          SemanticsAction action,
          fml::MallocMapping args) = 0;
  
      //--------------------------------------------------------------------------
      /// @brief      Notifies the delegate that the embedder has expressed an
      ///             opinion about whether the accessibility tree needs to be
      ///             enabled or disabled. This information needs to be forwarded
      ///             to the root isolate running on the UI thread.
      ///
      /// @param[in]  enabled  Whether the accessibility tree is enabled or
      ///                      disabled.
      ///
      virtual void OnPlatformViewSetSemanticsEnabled(bool enabled) = 0;
  
      //--------------------------------------------------------------------------
      /// @brief      Notifies the delegate that the embedder has expressed an
      ///             opinion about the features to enable in the accessibility
      ///             tree.
      ///
      ///             The engine does not care about the accessibility feature
      ///             flags as all it does is forward this information from the
      ///             embedder to the framework. However, curious readers may
      ///             refer to `AccessibilityFeatures` in `window.dart` for
      ///             currently supported accessibility feature flags.
      ///
      /// @param[in]  flags  The features to enable in the accessibility tree.
      ///
      virtual void OnPlatformViewSetAccessibilityFeatures(int32_t flags) = 0;
  
      //--------------------------------------------------------------------------
      /// @brief      Notifies the delegate that the embedder has specified a
      ///             texture that it want the rasterizer to composite within the
      ///             Flutter layer tree. All textures must have a unique
      ///             identifier. When the rasterizer encounters an external
      ///             texture within its hierarchy, it gives the embedder a chance
      ///             to update that texture on the raster thread before it
      ///             composites the same on-screen.
      ///
      /// @param[in]  texture  The texture that is being updated by the embedder
      ///                      but composited by Flutter in its own hierarchy.
      ///
      virtual void OnPlatformViewRegisterTexture(
          std::shared_ptr<Texture> texture) = 0;
  
      //--------------------------------------------------------------------------
      /// @brief      Notifies the delegate that the embedder will no longer
      ///             attempt to composite the specified texture within the layer
      ///             tree. This allows the rasterizer to collect associated
      ///             resources.
      ///
      /// @param[in]  texture_id  The identifier of the texture to unregister. If
      ///                         the texture has not been previously registered,
      ///                         this call does nothing.
      ///
      virtual void OnPlatformViewUnregisterTexture(int64_t texture_id) = 0;
  
      //--------------------------------------------------------------------------
      /// @brief      Notifies the delegate that the embedder has updated the
      ///             contents of the texture with the specified identifier.
      ///             Typically, Flutter will only render a frame if there is an
      ///             updated layer tree. However, in cases where the layer tree
      ///             is static but one of the externally composited textures has
      ///             been updated by the embedder, the embedder needs to notify
      ///             the rasterizer to render a new frame. In such cases, the
      ///             existing layer tree may be reused with the frame composited
      ///             with all updated external textures.
      ///
      /// @param[in]  texture_id  The identifier of the texture that has been
      ///                         updated.
      ///
      virtual void OnPlatformViewMarkTextureFrameAvailable(
          int64_t texture_id) = 0;
  
      //--------------------------------------------------------------------------
      /// @brief      Loads the dart shared library into the dart VM. When the
      ///             dart library is loaded successfully, the dart future
      ///             returned by the originating loadLibrary() call completes.
      ///
      ///             The Dart compiler may generate separate shared libraries
      ///             files called 'loading units' when libraries are imported
      ///             as deferred. Each of these shared libraries are identified
      ///             by a unique loading unit id. Callers should open and resolve
      ///             a SymbolMapping from the shared library. The Mappings should
      ///             be moved into this method, as ownership will be assumed by
      ///             the dart root isolate after successful loading and released
      ///             after shutdown of the root isolate. The loading unit may not
      ///             be used after isolate shutdown. If loading fails, the
      ///             mappings will be released.
      ///
      ///             This method is paired with a RequestDartDeferredLibrary
      ///             invocation that provides the embedder with the loading unit
      ///             id of the deferred library to load.
      ///
      ///
      /// @param[in]  loading_unit_id  The unique id of the deferred library's
      ///                              loading unit.
      ///
      /// @param[in]  snapshot_data    Dart snapshot data of the loading unit's
      ///                              shared library.
      ///
      /// @param[in]  snapshot_data    Dart snapshot instructions of the loading
      ///                              unit's shared library.
      ///
      virtual void LoadDartDeferredLibrary(
          intptr_t loading_unit_id,
          std::unique_ptr<const fml::Mapping> snapshot_data,
          std::unique_ptr<const fml::Mapping> snapshot_instructions) = 0;
  
      //--------------------------------------------------------------------------
      /// @brief      Indicates to the dart VM that the request to load a deferred
      ///             library with the specified loading unit id has failed.
      ///
      ///             The dart future returned by the initiating loadLibrary()
      ///             call will complete with an error.
      ///
      /// @param[in]  loading_unit_id  The unique id of the deferred library's
      ///                              loading unit, as passed in by
      ///                              RequestDartDeferredLibrary.
      ///
      /// @param[in]  error_message    The error message that will appear in the
      ///                              dart Future.
      ///
      /// @param[in]  transient        A transient error is a failure due to
      ///                              temporary conditions such as no network.
      ///                              Transient errors allow the dart VM to
      ///                              re-request the same deferred library and
      ///                              and loading_unit_id again. Non-transient
      ///                              errors are permanent and attempts to
      ///                              re-request the library will instantly
      ///                              complete with an error.
      virtual void LoadDartDeferredLibraryError(intptr_t loading_unit_id,
                                                const std::string error_message,
                                                bool transient) = 0;
  
      //--------------------------------------------------------------------------
      /// @brief      Replaces the asset resolver handled by the engine's
      ///             AssetManager of the specified `type` with
      ///             `updated_asset_resolver`. The matching AssetResolver is
      ///             removed and replaced with `updated_asset_resolvers`.
      ///
      ///             AssetResolvers should be updated when the existing resolver
      ///             becomes obsolete and a newer one becomes available that
      ///             provides updated access to the same type of assets as the
      ///             existing one. This update process is meant to be performed
      ///             at runtime.
      ///
      ///             If a null resolver is provided, nothing will be done. If no
      ///             matching resolver is found, the provided resolver will be
      ///             added to the end of the AssetManager resolvers queue. The
      ///             replacement only occurs with the first matching resolver.
      ///             Any additional matching resolvers are untouched.
      ///
      /// @param[in]  updated_asset_resolver  The asset resolver to replace the
      ///             resolver of matching type with.
      ///
      /// @param[in]  type  The type of AssetResolver to update. Only resolvers of
      ///                   the specified type will be replaced by the updated
      ///                   resolver.
      ///
      virtual void UpdateAssetResolverByType(
          std::unique_ptr<AssetResolver> updated_asset_resolver,
          AssetResolver::AssetResolverType type) = 0;
    };
  
    //----------------------------------------------------------------------------
    /// @brief      Creates a platform view with the specified delegate and task
    ///             runner. The base class by itself does not do much but is
    ///             suitable for use in test environments where full platform
    ///             integration may not be necessary. The platform view may only
    ///             be created, accessed and destroyed on the platform task
    ///             runner.
    ///
    /// @param      delegate      The delegate. This is typically the shell.
    /// @param[in]  task_runners  The task runners used by this platform view.
    ///
    explicit PlatformView(Delegate& delegate, TaskRunners task_runners);
  
    //----------------------------------------------------------------------------
    /// @brief      Destroys the platform view. The platform view is owned by the
    ///             shell and will be destroyed by the same on the platform tasks
    ///             runner.
    ///
    virtual ~PlatformView();
  
    //----------------------------------------------------------------------------
    /// @brief      Invoked by the shell to obtain a platform specific vsync
    ///             waiter. It is optional for platforms to override this method
    ///             and provide a custom vsync waiter because a timer based
    ///             fall-back waiter is used by default. However, it is highly
    ///             recommended that platform provide their own Vsync waiter as
    ///             the timer based fall-back will not render frames aligned with
    ///             vsync boundaries.
    ///
    /// @attention  If a timer based fall-back is used, a warning is logged to the
    ///             console. In case this method is overridden in a subclass, it
    ///             must return a valid vsync waiter. Returning null will lead to
    ///             internal errors. If a valid vsync waiter cannot be returned,
    ///             subclasses should just call the based class method instead.
    ///
    /// @return     A vsync waiter. If is an internal error to return a null
    ///             waiter.
    ///
    virtual std::unique_ptr<VsyncWaiter> CreateVSyncWaiter();
  
    //----------------------------------------------------------------------------
    /// @brief      Used by embedders to dispatch a platform message to a
    ///             running root isolate hosted by the engine. If an isolate is
    ///             not running, the message is dropped. If there is no one on the
    ///             other side listening on the channel, the message is dropped.
    ///             When a platform message is dropped, any response handles
    ///             associated with that message will be dropped as well. All
    ///             users of platform messages must assume that message may not be
    ///             delivered and/or their response handles may not be invoked.
    ///             Platform messages are not buffered.
    ///
    ///             For embedders that wish to respond to platform message
    ///             directed from the framework to the embedder, the
    ///             `HandlePlatformMessage` method may be overridden.
    ///
    /// @see        HandlePlatformMessage()
    ///
    /// @param[in]  message  The platform message to deliver to the root isolate.
    ///
    void DispatchPlatformMessage(std::unique_ptr<PlatformMessage> message);
  
    //----------------------------------------------------------------------------
    /// @brief      Overridden by embedders to perform actions in response to
    ///             platform messages sent from the framework to the embedder.
    ///             Default implementation of this method simply returns an empty
    ///             response.
    ///
    ///             Embedders that wish to send platform messages to the framework
    ///             may use the `DispatchPlatformMessage` method. This method is
    ///             for messages that go the other way.
    ///
    /// @see        DispatchPlatformMessage()
    ///
    /// @param[in]  message  The message
    ///
    virtual void HandlePlatformMessage(std::unique_ptr<PlatformMessage> message);
  
    //----------------------------------------------------------------------------
    /// @brief      Used by embedders to dispatch an accessibility action to a
    ///             running isolate hosted by the engine.
    ///
    /// @param[in]  id      The identifier of the accessibility node on which to
    ///                     perform the action.
    /// @param[in]  action  The action
    /// @param[in]  args    The arguments
    ///
    void DispatchSemanticsAction(int32_t id,
                                 SemanticsAction action,
                                 fml::MallocMapping args);
  
    //----------------------------------------------------------------------------
    /// @brief      Used by embedder to notify the running isolate hosted by the
    ///             engine on the UI thread that the accessibility tree needs to
    ///             be generated.
    ///
    /// @attention  Subclasses may choose to override this method to perform
    ///             platform specific functions. However, they must call the base
    ///             class method at some point in their implementation.
    ///
    /// @param[in]  enabled  Whether the accessibility tree needs to be generated.
    ///
    virtual void SetSemanticsEnabled(bool enabled);
  
    //----------------------------------------------------------------------------
    /// @brief      Used by the embedder to specify the features to enable in the
    ///             accessibility tree generated by the isolate. This information
    ///             is forwarded to the root isolate hosted by the engine on the
    ///             UI thread.
    ///
    ///             The engine does not care about the accessibility feature flags
    ///             as all it does is forward this information from the embedder
    ///             to the framework. However, curious readers may refer to
    ///             `AccessibilityFeatures` in `window.dart` for currently
    ///             supported accessibility feature flags.
    ///
    /// @attention  Subclasses may choose to override this method to perform
    ///             platform specific functions. However, they must call the base
    ///             class method at some point in their implementation.
    ///
    /// @param[in]  flags  The features to enable in the accessibility tree.
    ///
    virtual void SetAccessibilityFeatures(int32_t flags);
  
    //----------------------------------------------------------------------------
    /// @brief      Used by the framework to tell the embedder to apply the
    ///             specified semantics node updates. The default implementation
    ///             of this method does nothing.
    ///
    /// @see        SemanticsNode, SemticsNodeUpdates,
    ///             CustomAccessibilityActionUpdates
    ///
    /// @param[in]  updates  A map with the stable semantics node identifier as
    ///                      key and the node properties as the value.
    /// @param[in]  actions  A map with the stable semantics node identifier as
    ///                      key and the custom node action as the value.
    ///
    virtual void UpdateSemantics(SemanticsNodeUpdates updates,
                                 CustomAccessibilityActionUpdates actions);
  
    //----------------------------------------------------------------------------
    /// @brief      Used by embedders to specify the updated viewport metrics. In
    ///             response to this call, on the raster thread, the rasterizer
    ///             may need to be reconfigured to the updated viewport
    ///             dimensions. On the UI thread, the framework may need to start
    ///             generating a new frame for the updated viewport metrics as
    ///             well.
    ///
    /// @param[in]  metrics  The updated viewport metrics.
    ///
    void SetViewportMetrics(const ViewportMetrics& metrics);
  
    //----------------------------------------------------------------------------
    /// @brief      Used by embedders to notify the shell that a platform view
    ///             has been created. This notification is used to create a
    ///             rendering surface and pick the client rendering API to use to
    ///             render into this surface. No frames will be scheduled or
    ///             rendered before this call. The surface must remain valid till
    ///             the corresponding call to NotifyDestroyed.
    ///
    void NotifyCreated();
  
    //----------------------------------------------------------------------------
    /// @brief      Used by embedders to notify the shell that the platform view
    ///             has been destroyed. This notification used to collect the
    ///             rendering surface and all associated resources. Frame
    ///             scheduling is also suspended.
    ///
    /// @attention  Subclasses may choose to override this method to perform
    ///             platform specific functions. However, they must call the base
    ///             class method at some point in their implementation.
    ///
    virtual void NotifyDestroyed();
  
    //----------------------------------------------------------------------------
    /// @brief      Used by the shell to obtain a Skia GPU context that is capable
    ///             of operating on the IO thread. The context must be in the same
    ///             share-group as the Skia GPU context used on the render thread.
    ///             This context will always be used on the IO thread. Because it
    ///             is in the same share-group as the separate render thread
    ///             context, any GPU resources uploaded in this context will be
    ///             visible to the render thread context (synchronization of GPU
    ///             resources is managed by Skia).
    ///
    ///             If such context cannot be created on the IO thread, callers
    ///             may return `nullptr`. This will mean that all texture uploads
    ///             will be queued onto the render thread which will cause
    ///             performance issues. When this context is `nullptr`, an error
    ///             is logged to the console. It is highly recommended that all
    ///             platforms provide a resource context.
    ///
    /// @attention  Unlike all other methods on the platform view, this will be
    ///             called on IO task runner.
    ///
    /// @return     The Skia GPU context that is in the same share-group as the
    ///             main render thread GPU context. May be `nullptr` in case such
    ///             a context cannot be created.
    ///
    virtual sk_sp<GrDirectContext> CreateResourceContext() const;
  
    //----------------------------------------------------------------------------
    /// @brief      Used by the shell to notify the embedder that the resource
    ///             context previously obtained via a call to
    ///             `CreateResourceContext()` is being collected. The embedder is
    ///             free to collect an platform specific resources associated with
    ///             this context.
    ///
    /// @attention  Unlike all other methods on the platform view, this will be
    ///             called on IO task runner.
    ///
    virtual void ReleaseResourceContext() const;
  
    //--------------------------------------------------------------------------
    /// @brief      Returns a platform-specific PointerDataDispatcherMaker so the
    ///             `Engine` can construct the PointerDataPacketDispatcher based
    ///             on platforms.
    virtual PointerDataDispatcherMaker GetDispatcherMaker();
  
    //----------------------------------------------------------------------------
    /// @brief      Returns a weak pointer to the platform view. Since the
    ///             platform view may only be created, accessed and destroyed
    ///             on the platform thread, any access to the platform view
    ///             from a non-platform task runner needs a weak pointer to
    ///             the platform view along with a reference to the platform
    ///             task runner. A task must be posted to the platform task
    ///             runner with the weak pointer captured in the same. The
    ///             platform view method may only be called in the posted task
    ///             once the weak pointer validity has been checked. This
    ///             method is used by callers to obtain that weak pointer.
    ///
    /// @return     The weak pointer to the platform view.
    ///
    fml::WeakPtr<PlatformView> GetWeakPtr() const;
  
    //----------------------------------------------------------------------------
    /// @brief      Gives embedders a chance to react to a "cold restart" of the
    ///             running isolate. The default implementation of this method
    ///             does nothing.
    ///
    ///             While a "hot restart" patches a running isolate, a "cold
    ///             restart" restarts the root isolate in a running shell.
    ///
    virtual void OnPreEngineRestart() const;
  
    //----------------------------------------------------------------------------
    /// @brief      Sets a callback that gets executed when the rasterizer renders
    ///             the next frame. Due to the asynchronous nature of
    ///             rendering in Flutter, embedders usually add a placeholder
    ///             over the contents in which Flutter is going to render when
    ///             Flutter is first initialized. This callback may be used as
    ///             a signal to remove that placeholder. The callback is
    ///             executed on the render task runner and not the platform
    ///             task runner. It is the embedder's responsibility to
    ///             re-thread as necessary.
    ///
    /// @attention  The callback is executed on the render task runner and not the
    ///             platform task runner. Embedders must re-thread as necessary.
    ///
    /// @param[in]  closure  The callback to execute on the render thread when the
    ///                      next frame gets rendered.
    ///
    void SetNextFrameCallback(const fml::closure& closure);
  
    //----------------------------------------------------------------------------
    /// @brief      Dispatches pointer events from the embedder to the
    ///             framework. Each pointer data packet may contain multiple
    ///             pointer input events. Each call to this method wakes up
    ///             the UI thread.
    ///
    /// @param[in]  packet  The pointer data packet to dispatch to the framework.
    ///
    void DispatchPointerDataPacket(std::unique_ptr<PointerDataPacket> packet);
  
    //--------------------------------------------------------------------------
    /// @brief      Used by the embedder to specify a texture that it wants the
    ///             rasterizer to composite within the Flutter layer tree. All
    ///             textures must have a unique identifier. When the
    ///             rasterizer encounters an external texture within its
    ///             hierarchy, it gives the embedder a chance to update that
    ///             texture on the raster thread before it composites the same
    ///             on-screen.
    ///
    /// @attention  This method must only be called once per texture. When the
    ///             texture is updated, calling `MarkTextureFrameAvailable`
    ///             with the specified texture identifier is sufficient to
    ///             make Flutter re-render the frame with the updated texture
    ///             composited in-line.
    ///
    /// @see        UnregisterTexture, MarkTextureFrameAvailable
    ///
    /// @param[in]  texture  The texture that is being updated by the embedder
    ///                      but composited by Flutter in its own hierarchy.
    ///
    void RegisterTexture(std::shared_ptr<flutter::Texture> texture);
  
    //--------------------------------------------------------------------------
    /// @brief      Used by the embedder to notify the rasterizer that it will
    /// no
    ///             longer attempt to composite the specified texture within
    ///             the layer tree. This allows the rasterizer to collect
    ///             associated resources.
    ///
    /// @attention  This call must only be called once per texture identifier.
    ///
    /// @see        RegisterTexture, MarkTextureFrameAvailable
    ///
    /// @param[in]  texture_id  The identifier of the texture to unregister. If
    ///                         the texture has not been previously registered,
    ///                         this call does nothing.
    ///
    void UnregisterTexture(int64_t texture_id);
  
    //--------------------------------------------------------------------------
    /// @brief      Used by the embedder to notify the rasterizer that the context
    ///             of the previously registered texture have been updated.
    ///             Typically, Flutter will only render a frame if there is an
    ///             updated layer tree. However, in cases where the layer tree
    ///             is static but one of the externally composited textures
    ///             has been updated by the embedder, the embedder needs to
    ///             notify the rasterizer to render a new frame. In such
    ///             cases, the existing layer tree may be reused with the
    ///             frame re-composited with all updated external textures.
    ///             Unlike the calls to register and unregister the texture,
    ///             this call must be made each time a new texture frame is
    ///             available.
    ///
    /// @see        RegisterTexture, UnregisterTexture
    ///
    /// @param[in]  texture_id  The identifier of the texture that has been
    ///                         updated.
    ///
    void MarkTextureFrameAvailable(int64_t texture_id);
  
    //--------------------------------------------------------------------------
    /// @brief      Directly invokes platform-specific APIs to compute the
    ///             locale the platform would have natively resolved to.
    ///
    /// @param[in]  supported_locale_data  The vector of strings that represents
    ///                                    the locales supported by the app.
    ///                                    Each locale consists of three
    ///                                    strings: languageCode, countryCode,
    ///                                    and scriptCode in that order.
    ///
    /// @return     A vector of 3 strings languageCode, countryCode, and
    ///             scriptCode that represents the locale selected by the
    ///             platform. Empty strings mean the value was unassigned. Empty
    ///             vector represents a null locale.
    ///
    virtual std::unique_ptr<std::vector<std::string>>
    ComputePlatformResolvedLocales(
        const std::vector<std::string>& supported_locale_data);
  
    virtual std::shared_ptr<ExternalViewEmbedder> CreateExternalViewEmbedder();
  
    //--------------------------------------------------------------------------
    /// @brief      Invoked when the dart VM requests that a deferred library
    ///             be loaded. Notifies the engine that the deferred library
    ///             identified by the specified loading unit id should be
    ///             downloaded and loaded into the Dart VM via
    ///             `LoadDartDeferredLibrary`
    ///
    ///             Upon encountering errors or otherwise failing to load a
    ///             loading unit with the specified id, the failure should be
    ///             directly reported to dart by calling
    ///             `LoadDartDeferredLibraryFailure` to ensure the waiting dart
    ///             future completes with an error.
    ///
    /// @param[in]  loading_unit_id  The unique id of the deferred library's
    ///                              loading unit. This id is to be passed
    ///                              back into LoadDartDeferredLibrary
    ///                              in order to identify which deferred
    ///                              library to load.
    ///
    virtual void RequestDartDeferredLibrary(intptr_t loading_unit_id);
  
    //--------------------------------------------------------------------------
    /// @brief      Loads the Dart shared library into the Dart VM. When the
    ///             Dart library is loaded successfully, the Dart future
    ///             returned by the originating loadLibrary() call completes.
    ///
    ///             The Dart compiler may generate separate shared libraries
    ///             files called 'loading units' when libraries are imported
    ///             as deferred. Each of these shared libraries are identified
    ///             by a unique loading unit id. Callers should open and resolve
    ///             a SymbolMapping from the shared library. The Mappings should
    ///             be moved into this method, as ownership will be assumed by the
    ///             dart isolate after successful loading and released after
    ///             shutdown of the dart isolate. If loading fails, the mappings
    ///             will naturally go out of scope.
    ///
    ///             This method is paired with a RequestDartDeferredLibrary
    ///             invocation that provides the embedder with the loading unit id
    ///             of the deferred library to load.
    ///
    ///
    /// @param[in]  loading_unit_id  The unique id of the deferred library's
    ///                              loading unit, as passed in by
    ///                              RequestDartDeferredLibrary.
    ///
    /// @param[in]  snapshot_data    Dart snapshot data of the loading unit's
    ///                              shared library.
    ///
    /// @param[in]  snapshot_data    Dart snapshot instructions of the loading
    ///                              unit's shared library.
    ///
    virtual void LoadDartDeferredLibrary(
        intptr_t loading_unit_id,
        std::unique_ptr<const fml::Mapping> snapshot_data,
        std::unique_ptr<const fml::Mapping> snapshot_instructions);
  
    //--------------------------------------------------------------------------
    /// @brief      Indicates to the dart VM that the request to load a deferred
    ///             library with the specified loading unit id has failed.
    ///
    ///             The dart future returned by the initiating loadLibrary() call
    ///             will complete with an error.
    ///
    /// @param[in]  loading_unit_id  The unique id of the deferred library's
    ///                              loading unit, as passed in by
    ///                              RequestDartDeferredLibrary.
    ///
    /// @param[in]  error_message    The error message that will appear in the
    ///                              dart Future.
    ///
    /// @param[in]  transient        A transient error is a failure due to
    ///                              temporary conditions such as no network.
    ///                              Transient errors allow the dart VM to
    ///                              re-request the same deferred library and
    ///                              and loading_unit_id again. Non-transient
    ///                              errors are permanent and attempts to
    ///                              re-request the library will instantly
    ///                              complete with an error.
    ///
    virtual void LoadDartDeferredLibraryError(intptr_t loading_unit_id,
                                              const std::string error_message,
                                              bool transient);
  
    //--------------------------------------------------------------------------
    /// @brief      Replaces the asset resolver handled by the engine's
    ///             AssetManager of the specified `type` with
    ///             `updated_asset_resolver`. The matching AssetResolver is
    ///             removed and replaced with `updated_asset_resolvers`.
    ///
    ///             AssetResolvers should be updated when the existing resolver
    ///             becomes obsolete and a newer one becomes available that
    ///             provides updated access to the same type of assets as the
    ///             existing one. This update process is meant to be performed
    ///             at runtime.
    ///
    ///             If a null resolver is provided, nothing will be done. If no
    ///             matching resolver is found, the provided resolver will be
    ///             added to the end of the AssetManager resolvers queue. The
    ///             replacement only occurs with the first matching resolver.
    ///             Any additional matching resolvers are untouched.
    ///
    /// @param[in]  updated_asset_resolver  The asset resolver to replace the
    ///             resolver of matching type with.
    ///
    /// @param[in]  type  The type of AssetResolver to update. Only resolvers of
    ///                   the specified type will be replaced by the updated
    ///                   resolver.
    ///
    virtual void UpdateAssetResolverByType(
        std::unique_ptr<AssetResolver> updated_asset_resolver,
        AssetResolver::AssetResolverType type);
  
    //--------------------------------------------------------------------------
    /// @brief      Creates an object that produces surfaces suitable for raster
    ///             snapshotting. The rasterizer will request this surface if no
    ///             on screen surface is currently available when an application
    ///             requests a snapshot, e.g. if `Scene.toImage` or
    ///             `Picture.toImage` are called while the application is in the
    ///             background.
    ///
    ///             Not all backends support this kind of surface usage, and the
    ///             default implementation returns nullptr. Platforms should
    ///             override this if they can support GPU operations in the
    ///             background and support GPU resource context usage.
    ///
    virtual std::unique_ptr<SnapshotSurfaceProducer>
    CreateSnapshotSurfaceProducer();
  
    //--------------------------------------------------------------------------
    /// @brief Specifies a delegate that will receive PlatformMessages from
    /// Flutter to the host platform.
    ///
    /// @details If this returns `null` that means PlatformMessages should be sent
    /// to the PlatformView.  That is to protect legacy behavior, any embedder
    /// that wants to support executing Platform Channel handlers on background
    /// threads should be returing a thread-safe PlatformMessageHandler instead.
    virtual std::shared_ptr<PlatformMessageHandler> GetPlatformMessageHandler()
        const;
  
   protected:
    // This is the only method called on the raster task runner.
    virtual std::unique_ptr<Surface> CreateRenderingSurface();
  
    PlatformView::Delegate& delegate_;
    const TaskRunners task_runners_;
    PointerDataPacketConverter pointer_data_packet_converter_;
    fml::WeakPtrFactory<PlatformView> weak_factory_;  // Must be the last member.
  
   private:
    FML_DISALLOW_COPY_AND_ASSIGN(PlatformView);
  };
  
  }  // namespace flutter
  
  #endif  // COMMON_PLATFORM_VIEW_H_
  