| 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_COMMON_SETTINGS_H_ |
| 6 | #define FLUTTER_COMMON_SETTINGS_H_ |
| 7 | |
| 8 | #include <fcntl.h> |
| 9 | |
| 10 | #include <chrono> |
| 11 | #include <cstdint> |
| 12 | #include <memory> |
| 13 | #include <optional> |
| 14 | #include <string> |
| 15 | #include <vector> |
| 16 | |
| 17 | #include "flutter/fml/build_config.h" |
| 18 | #include "flutter/fml/closure.h" |
| 19 | #include "flutter/fml/mapping.h" |
| 20 | #include "flutter/fml/time/time_point.h" |
| 21 | #include "flutter/fml/unique_fd.h" |
| 22 | |
| 23 | namespace flutter { |
| 24 | |
| 25 | class FrameTiming { |
| 26 | public: |
| 27 | enum Phase { |
| 28 | kVsyncStart, |
| 29 | kBuildStart, |
| 30 | kBuildFinish, |
| 31 | kRasterStart, |
| 32 | kRasterFinish, |
| 33 | kRasterFinishWallTime, |
| 34 | kCount |
| 35 | }; |
| 36 | |
| 37 | static constexpr Phase kPhases[kCount] = { |
| 38 | kVsyncStart, kBuildStart, kBuildFinish, |
| 39 | kRasterStart, kRasterFinish, kRasterFinishWallTime}; |
| 40 | |
| 41 | static constexpr int kStatisticsCount = kCount + 5; |
| 42 | |
| 43 | fml::TimePoint Get(Phase phase) const { return data_[phase]; } |
| 44 | fml::TimePoint Set(Phase phase, fml::TimePoint value) { |
| 45 | return data_[phase] = value; |
| 46 | } |
| 47 | |
| 48 | uint64_t () const { return frame_number_; } |
| 49 | void (uint64_t frame_number) { frame_number_ = frame_number; } |
| 50 | uint64_t GetLayerCacheCount() const { return layer_cache_count_; } |
| 51 | uint64_t GetLayerCacheBytes() const { return layer_cache_bytes_; } |
| 52 | uint64_t GetPictureCacheCount() const { return picture_cache_count_; } |
| 53 | uint64_t GetPictureCacheBytes() const { return picture_cache_bytes_; } |
| 54 | void SetRasterCacheStatistics(size_t layer_cache_count, |
| 55 | size_t layer_cache_bytes, |
| 56 | size_t picture_cache_count, |
| 57 | size_t picture_cache_bytes) { |
| 58 | layer_cache_count_ = layer_cache_count; |
| 59 | layer_cache_bytes_ = layer_cache_bytes; |
| 60 | picture_cache_count_ = picture_cache_count; |
| 61 | picture_cache_bytes_ = picture_cache_bytes; |
| 62 | } |
| 63 | |
| 64 | private: |
| 65 | fml::TimePoint data_[kCount]; |
| 66 | uint64_t frame_number_; |
| 67 | size_t layer_cache_count_; |
| 68 | size_t layer_cache_bytes_; |
| 69 | size_t picture_cache_count_; |
| 70 | size_t picture_cache_bytes_; |
| 71 | }; |
| 72 | |
| 73 | using TaskObserverAdd = |
| 74 | std::function<void(intptr_t /* key */, fml::closure /* callback */)>; |
| 75 | using TaskObserverRemove = std::function<void(intptr_t /* key */)>; |
| 76 | using UnhandledExceptionCallback = |
| 77 | std::function<bool(const std::string& /* error */, |
| 78 | const std::string& /* stack trace */)>; |
| 79 | using LogMessageCallback = |
| 80 | std::function<void(const std::string& /* tag */, |
| 81 | const std::string& /* message */)>; |
| 82 | |
| 83 | // TODO(26783): Deprecate all the "path" struct members in favor of the |
| 84 | // callback that generates the mapping from these paths. |
| 85 | using MappingCallback = std::function<std::unique_ptr<fml::Mapping>(void)>; |
| 86 | using Mappings = std::vector<std::unique_ptr<const fml::Mapping>>; |
| 87 | using MappingsCallback = std::function<Mappings(void)>; |
| 88 | |
| 89 | using FrameRasterizedCallback = std::function<void(const FrameTiming&)>; |
| 90 | |
| 91 | class DartIsolate; |
| 92 | |
| 93 | struct Settings { |
| 94 | Settings(); |
| 95 | |
| 96 | Settings(const Settings& other); |
| 97 | |
| 98 | ~Settings(); |
| 99 | |
| 100 | /// Determines if attempts at grabbing the Surface's SurfaceData can be |
| 101 | /// attempted. |
| 102 | static constexpr bool kSurfaceDataAccessible = |
| 103 | #ifdef _NDEBUG |
| 104 | false; |
| 105 | #else |
| 106 | true; |
| 107 | #endif |
| 108 | |
| 109 | // VM settings |
| 110 | std::string vm_snapshot_data_path; // deprecated |
| 111 | MappingCallback vm_snapshot_data; |
| 112 | std::string vm_snapshot_instr_path; // deprecated |
| 113 | MappingCallback vm_snapshot_instr; |
| 114 | |
| 115 | std::string isolate_snapshot_data_path; // deprecated |
| 116 | MappingCallback isolate_snapshot_data; |
| 117 | std::string isolate_snapshot_instr_path; // deprecated |
| 118 | MappingCallback isolate_snapshot_instr; |
| 119 | |
| 120 | std::string route; |
| 121 | |
| 122 | // Returns the Mapping to a kernel buffer which contains sources for dart:* |
| 123 | // libraries. |
| 124 | MappingCallback dart_library_sources_kernel; |
| 125 | |
| 126 | // Path to a library containing the application's compiled Dart code. |
| 127 | // This is a vector so that the embedder can provide fallback paths in |
| 128 | // case the primary path to the library can not be loaded. |
| 129 | std::vector<std::string> application_library_path; |
| 130 | |
| 131 | // Path to a library containing compiled Dart code usable for launching |
| 132 | // the VM service isolate. |
| 133 | std::vector<std::string> vmservice_snapshot_library_path; |
| 134 | |
| 135 | std::string application_kernel_asset; // deprecated |
| 136 | std::string application_kernel_list_asset; // deprecated |
| 137 | MappingsCallback application_kernels; |
| 138 | |
| 139 | std::string temp_directory_path; |
| 140 | std::vector<std::string> dart_flags; |
| 141 | // Isolate settings |
| 142 | bool enable_checked_mode = false; |
| 143 | bool start_paused = false; |
| 144 | bool trace_skia = false; |
| 145 | std::vector<std::string> trace_allowlist; |
| 146 | std::optional<std::vector<std::string>> trace_skia_allowlist; |
| 147 | bool trace_startup = false; |
| 148 | bool trace_systrace = false; |
| 149 | bool enable_timeline_event_handler = true; |
| 150 | bool dump_skp_on_shader_compilation = false; |
| 151 | bool cache_sksl = false; |
| 152 | bool purge_persistent_cache = false; |
| 153 | bool endless_trace_buffer = false; |
| 154 | bool enable_dart_profiling = false; |
| 155 | bool disable_dart_asserts = false; |
| 156 | bool enable_serial_gc = false; |
| 157 | |
| 158 | // Whether embedder only allows secure connections. |
| 159 | bool may_insecurely_connect_to_all_domains = true; |
| 160 | // JSON-formatted domain network policy. |
| 161 | std::string domain_network_policy; |
| 162 | |
| 163 | // Used as the script URI in debug messages. Does not affect how the Dart code |
| 164 | // is executed. |
| 165 | std::string advisory_script_uri = "main.dart" ; |
| 166 | // Used as the script entrypoint in debug messages. Does not affect how the |
| 167 | // Dart code is executed. |
| 168 | std::string advisory_script_entrypoint = "main" ; |
| 169 | |
| 170 | // The executable path associated with this process. This is returned by |
| 171 | // Platform.executable from dart:io. If unknown, defaults to "Flutter". |
| 172 | std::string executable_name = "Flutter" ; |
| 173 | |
| 174 | // VM Service settings |
| 175 | |
| 176 | // Whether the Dart VM service should be enabled. |
| 177 | bool enable_vm_service = false; |
| 178 | |
| 179 | // Whether to publish the VM Service URL over mDNS. |
| 180 | // On iOS 14 this prompts a local network permission dialog, |
| 181 | // which cannot be accepted or dismissed in a CI environment. |
| 182 | bool enable_vm_service_publication = true; |
| 183 | |
| 184 | // The IP address to which the Dart VM service is bound. |
| 185 | std::string vm_service_host; |
| 186 | |
| 187 | // The port to which the Dart VM service is bound. When set to `0`, a free |
| 188 | // port will be automatically selected by the OS. A message is logged on the |
| 189 | // target indicating the URL at which the VM service can be accessed. |
| 190 | uint32_t vm_service_port = 0; |
| 191 | |
| 192 | // Determines whether an authentication code is required to communicate with |
| 193 | // the VM service. |
| 194 | bool disable_service_auth_codes = true; |
| 195 | |
| 196 | // Determine whether the vmservice should fallback to automatic port selection |
| 197 | // after failing to bind to a specified port. |
| 198 | bool enable_service_port_fallback = false; |
| 199 | |
| 200 | // Font settings |
| 201 | bool use_test_fonts = false; |
| 202 | |
| 203 | bool use_asset_fonts = true; |
| 204 | |
| 205 | // Indicates whether the embedding started a prefetch of the default font |
| 206 | // manager before creating the engine. |
| 207 | bool prefetched_default_font_manager = false; |
| 208 | |
| 209 | // Enable the rendering of colors outside of the sRGB gamut. |
| 210 | bool enable_wide_gamut = false; |
| 211 | |
| 212 | // Enable the Impeller renderer on supported platforms. Ignored if Impeller is |
| 213 | // not supported on the platform. |
| 214 | #if FML_OS_IOS || FML_OS_IOS_SIMULATOR |
| 215 | bool enable_impeller = true; |
| 216 | #else |
| 217 | bool enable_impeller = false; |
| 218 | #endif |
| 219 | |
| 220 | // Requests a particular backend to be used (ex "opengles" or "vulkan") |
| 221 | std::optional<std::string> impeller_backend; |
| 222 | |
| 223 | // Enable Vulkan validation on backends that support it. The validation layers |
| 224 | // must be available to the application. |
| 225 | bool enable_vulkan_validation = false; |
| 226 | |
| 227 | // Data set by platform-specific embedders for use in font initialization. |
| 228 | uint32_t font_initialization_data = 0; |
| 229 | |
| 230 | // All shells in the process share the same VM. The last shell to shutdown |
| 231 | // should typically shut down the VM as well. However, applications depend on |
| 232 | // the behavior of "warming-up" the VM by creating a shell that does not do |
| 233 | // anything. This used to work earlier when the VM could not be shut down (and |
| 234 | // hence never was). Shutting down the VM now breaks such assumptions in |
| 235 | // existing embedders. To keep this behavior consistent and allow existing |
| 236 | // embedders the chance to migrate, this flag defaults to true. Any shell |
| 237 | // launched with this flag set to true will leak the VM in the process. There |
| 238 | // is no way to shut down the VM once such a shell has been started. All |
| 239 | // shells in the platform (via their embedding APIs) should cooperate to make |
| 240 | // sure this flag is never set if they want the VM to shutdown and free all |
| 241 | // associated resources. |
| 242 | // It can be customized by application, more detail: |
| 243 | // https://github.com/flutter/flutter/issues/95903 |
| 244 | // TODO(eggfly): Should it be set to false by default? |
| 245 | // https://github.com/flutter/flutter/issues/96843 |
| 246 | bool leak_vm = true; |
| 247 | |
| 248 | // Engine settings |
| 249 | TaskObserverAdd task_observer_add; |
| 250 | TaskObserverRemove task_observer_remove; |
| 251 | // The main isolate is current when this callback is made. This is a good spot |
| 252 | // to perform native Dart bindings for libraries not built in. |
| 253 | std::function<void(const DartIsolate&)> root_isolate_create_callback; |
| 254 | // TODO(68738): Update isolate callbacks in settings to accept an additional |
| 255 | // DartIsolate parameter. |
| 256 | fml::closure isolate_create_callback; |
| 257 | // The isolate is not current and may have already been destroyed when this |
| 258 | // call is made. |
| 259 | fml::closure root_isolate_shutdown_callback; |
| 260 | fml::closure isolate_shutdown_callback; |
| 261 | // A callback made in the isolate scope of the service isolate when it is |
| 262 | // launched. Care must be taken to ensure that callers are assigning callbacks |
| 263 | // to the settings object used to launch the VM. If an existing VM is used to |
| 264 | // launch an isolate using these settings, the callback will be ignored as the |
| 265 | // service isolate has already been launched. Also, this callback will only be |
| 266 | // made in the modes in which the service isolate is eligible for launch |
| 267 | // (debug and profile). |
| 268 | fml::closure service_isolate_create_callback; |
| 269 | // The callback made on the UI thread in an isolate scope when the engine |
| 270 | // detects that the framework is idle. The VM also uses this time to perform |
| 271 | // tasks suitable when idling. Due to this, embedders are still advised to be |
| 272 | // as fast as possible in returning from this callback. Long running |
| 273 | // operations in this callback do have the capability of introducing jank. |
| 274 | std::function<void(int64_t)> idle_notification_callback; |
| 275 | // A callback given to the embedder to react to unhandled exceptions in the |
| 276 | // running Flutter application. This callback is made on an internal engine |
| 277 | // managed thread and embedders must re-thread as necessary. Performing |
| 278 | // blocking calls in this callback will cause applications to jank. |
| 279 | UnhandledExceptionCallback unhandled_exception_callback; |
| 280 | // A callback given to the embedder to log print messages from the running |
| 281 | // Flutter application. This callback is made on an internal engine managed |
| 282 | // thread and embedders must re-thread if necessary. Performing blocking |
| 283 | // calls in this callback will cause applications to jank. |
| 284 | LogMessageCallback log_message_callback; |
| 285 | bool enable_software_rendering = false; |
| 286 | bool skia_deterministic_rendering_on_cpu = false; |
| 287 | bool verbose_logging = false; |
| 288 | std::string log_tag = "flutter" ; |
| 289 | |
| 290 | // The icu_initialization_required setting does not have a corresponding |
| 291 | // switch because it is intended to be decided during build time, not runtime. |
| 292 | // Some companies apply source modification here because their build system |
| 293 | // brings its own ICU data files. |
| 294 | bool icu_initialization_required = true; |
| 295 | std::string icu_data_path; |
| 296 | MappingCallback icu_mapper; |
| 297 | |
| 298 | // Assets settings |
| 299 | fml::UniqueFD::element_type assets_dir = |
| 300 | fml::UniqueFD::traits_type::InvalidValue(); |
| 301 | std::string assets_path; |
| 302 | |
| 303 | // Callback to handle the timings of a rasterized frame. This is called as |
| 304 | // soon as a frame is rasterized. |
| 305 | FrameRasterizedCallback frame_rasterized_callback; |
| 306 | |
| 307 | // This data will be available to the isolate immediately on launch via the |
| 308 | // PlatformDispatcher.getPersistentIsolateData callback. This is meant for |
| 309 | // information that the isolate cannot request asynchronously (platform |
| 310 | // messages can be used for that purpose). This data is held for the lifetime |
| 311 | // of the shell and is available on isolate restarts in the shell instance. |
| 312 | // Due to this, the buffer must be as small as possible. |
| 313 | std::shared_ptr<const fml::Mapping> persistent_isolate_data; |
| 314 | |
| 315 | /// Max size of old gen heap size in MB, or 0 for unlimited, -1 for default |
| 316 | /// value. |
| 317 | /// |
| 318 | /// See also: |
| 319 | /// https://github.com/dart-lang/sdk/blob/ca64509108b3e7219c50d6c52877c85ab6a35ff2/runtime/vm/flag_list.h#L150 |
| 320 | int64_t old_gen_heap_size = -1; |
| 321 | |
| 322 | // Max bytes threshold of resource cache, or 0 for unlimited. |
| 323 | size_t resource_cache_max_bytes_threshold = 0; |
| 324 | |
| 325 | /// The minimum number of samples to require in multipsampled anti-aliasing. |
| 326 | /// |
| 327 | /// Setting this value to 0 or 1 disables MSAA. |
| 328 | /// If it is not 0 or 1, it must be one of 2, 4, 8, or 16. However, if the |
| 329 | /// GPU does not support the requested sampling value, MSAA will be disabled. |
| 330 | uint8_t msaa_samples = 0; |
| 331 | |
| 332 | /// Enable embedder api on the embedder. |
| 333 | /// |
| 334 | /// This is currently only used by iOS. |
| 335 | bool enable_embedder_api = false; |
| 336 | }; |
| 337 | |
| 338 | } // namespace flutter |
| 339 | |
| 340 | #endif // FLUTTER_COMMON_SETTINGS_H_ |
| 341 | |