Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 57 additions & 21 deletions shell/platform/embedder/embedder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1503,6 +1503,37 @@ FlutterEngineResult FlutterEngineRunTask(FLUTTER_API_SYMBOL(FlutterEngine)
"Could not run the specified task.");
}

static bool DispatchJSONPlatformMessage(FLUTTER_API_SYMBOL(FlutterEngine)
engine,
rapidjson::Document document,
const std::string& channel_name) {
if (channel_name.size() == 0) {
return false;
}

rapidjson::StringBuffer buffer;
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);

if (!document.Accept(writer)) {
return false;
}

const char* message = buffer.GetString();

if (message == nullptr || buffer.GetSize() == 0) {
return false;
}

auto platform_message = fml::MakeRefCounted<flutter::PlatformMessage>(
channel_name.c_str(), // channel
std::vector<uint8_t>{message, message + buffer.GetSize()}, // message
nullptr // response
);

return reinterpret_cast<flutter::EmbedderEngine*>(engine)
->SendPlatformMessage(std::move(platform_message));
}

FlutterEngineResult FlutterEngineUpdateLocales(FLUTTER_API_SYMBOL(FlutterEngine)
engine,
const FlutterLocale** locales,
Expand Down Expand Up @@ -1555,27 +1586,8 @@ FlutterEngineResult FlutterEngineUpdateLocales(FLUTTER_API_SYMBOL(FlutterEngine)
}
document.AddMember("args", args, allocator);

rapidjson::StringBuffer buffer;
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
if (!document.Accept(writer)) {
return LOG_EMBEDDER_ERROR(kInternalInconsistency,
"Could not create locale payload.");
}

const char* message = buffer.GetString();

if (message == nullptr || buffer.GetSize() == 0) {
return LOG_EMBEDDER_ERROR(kInternalInconsistency,
"Could not create locale update message.");
}

auto platform_message = fml::MakeRefCounted<flutter::PlatformMessage>(
"flutter/localization", // channel
std::vector<uint8_t>{message, message + buffer.GetSize()}, // message
nullptr // response
);
return reinterpret_cast<flutter::EmbedderEngine*>(engine)
->SendPlatformMessage(std::move(platform_message))
return DispatchJSONPlatformMessage(engine, std::move(document),
"flutter/localization")
? kSuccess
: LOG_EMBEDDER_ERROR(kInternalInconsistency,
"Could not send message to update locale of "
Expand Down Expand Up @@ -1710,3 +1722,27 @@ FlutterEngineResult FlutterEnginePostDartObject(
typed_data_finalizer.Release();
return kSuccess;
}

FLUTTER_EXPORT
FlutterEngineResult FlutterEngineNotifyLowMemoryWarning(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider also calling Dart_NotifyLowMemory.

Copy link
Member Author

@chinmaygarde chinmaygarde Dec 17, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did not know that was a thing. I'll wire up in another patch. Thanks.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FLUTTER_API_SYMBOL(FlutterEngine) raw_engine) {
auto engine = reinterpret_cast<flutter::EmbedderEngine*>(raw_engine);
if (engine == nullptr || !engine->IsValid()) {
return LOG_EMBEDDER_ERROR(kInvalidArguments, "Engine was invalid.");
}

engine->GetShell().NotifyLowMemoryWarning();

rapidjson::Document document;
auto& allocator = document.GetAllocator();

document.SetObject();
document.AddMember("type", "memoryPressure", allocator);

return DispatchJSONPlatformMessage(raw_engine, std::move(document),
"flutter/system")
? kSuccess
: LOG_EMBEDDER_ERROR(
kInternalInconsistency,
"Could not dispatch the low memory notification message.");
}
23 changes: 22 additions & 1 deletion shell/platform/embedder/embedder.h
Original file line number Diff line number Diff line change
Expand Up @@ -1626,7 +1626,7 @@ bool FlutterEngineRunsAOTCompiledDartCode(void);
/// `FlutterEngineDeinitialize` or `FlutterEngineShutdown` on
/// another thread.
///
/// @param[in] engine. A running engine instance.
/// @param[in] engine A running engine instance.
/// @param[in] port The send port to send the object to.
/// @param[in] object The object to send to the isolate with the
/// corresponding receive port.
Expand All @@ -1639,6 +1639,27 @@ FlutterEngineResult FlutterEnginePostDartObject(
FlutterEngineDartPort port,
const FlutterEngineDartObject* object);

//------------------------------------------------------------------------------
/// @brief Posts a low memory notification to a running engine instance.
/// The engine will do its best to release non-critical resources in
/// response. It is not guaranteed that the resource would have been
/// collected by the time this call returns however. The
/// notification is posted to engine subsystems that may be
/// operating on other threads.
///
/// Flutter applications can respond to these notifications by
/// setting `WidgetsBindingObserver.didHaveMemoryPressure`
/// observers.
///
/// @param[in] engine A running engine instance.
///
/// @return If the low memory notification was sent to the running engine
/// instance.
///
FLUTTER_EXPORT
FlutterEngineResult FlutterEngineNotifyLowMemoryWarning(
FLUTTER_API_SYMBOL(FlutterEngine) engine);

#if defined(__cplusplus)
} // extern "C"
#endif
Expand Down
18 changes: 18 additions & 0 deletions shell/platform/embedder/tests/embedder_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3805,5 +3805,23 @@ TEST_F(EmbedderTest, ObjectsCanBePostedViaPorts) {
buffer_released_latch.Wait();
}

TEST_F(EmbedderTest, CanSendLowMemoryNotification) {
auto& context = GetEmbedderContext();

EmbedderConfigBuilder builder(context);
builder.SetSoftwareRendererConfig();

auto engine = builder.LaunchEngine();

ASSERT_TRUE(engine.is_valid());

// TODO(chinmaygarde): The shell ought to have a mechanism for notification
// dispatch that engine subsystems can register handlers to. This would allow
// the raster cache and the secondary context caches to respond to
// notifications. Once that is in place, this test can be updated to actually
// ensure that the dispatched message is visible to engine subsystems.
ASSERT_EQ(FlutterEngineNotifyLowMemoryWarning(engine.get()), kSuccess);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: We could check the Dart side gets the expected message if we added a .dart fixture here.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Roger, I'll address this TODO after addressing the other items in xreffed issue.

}

} // namespace testing
} // namespace flutter