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 4 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
4 changes: 4 additions & 0 deletions shell/platform/android/android_shell_holder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -182,4 +182,8 @@ fml::WeakPtr<PlatformViewAndroid> AndroidShellHolder::GetPlatformView() {
return platform_view_;
}

void AndroidShellHolder::NotifyLowMemoryWarning() {
FML_DCHECK(shell_);
shell_->NotifyLowMemoryWarning();
}
} // namespace flutter
2 changes: 2 additions & 0 deletions shell/platform/android/android_shell_holder.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ class AndroidShellHolder {

void UpdateAssetManager(fml::RefPtr<flutter::AssetManager> asset_manager);

void NotifyLowMemoryWarning();

private:
const flutter::Settings settings_;
const fml::jni::JavaObjectWeakGlobalRef java_object_;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -629,6 +629,9 @@ void onUserLeaveHint() {
void onTrimMemory(int level) {
ensureAlive();
if (flutterEngine != null) {
// This is always an indication that the Dart VM should collect memory
// and free any unneeded resources.
flutterEngine.getDartExecutor().notifyLowMemoryWarning();
// Use a trim level delivered while the application is running so the
// framework has a chance to react to the notification.
if (level == TRIM_MEMORY_RUNNING_LOW) {
Expand All @@ -651,6 +654,7 @@ void onTrimMemory(int level) {
void onLowMemory() {
Log.v(TAG, "Forwarding onLowMemory() to FlutterEngine.");
ensureAlive();
flutterEngine.getDartExecutor().notifyLowMemoryWarning();
flutterEngine.getSystemChannel().sendMemoryPressureWarning();
}

Expand Down
16 changes: 16 additions & 0 deletions shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java
Original file line number Diff line number Diff line change
Expand Up @@ -823,6 +823,22 @@ public Bitmap getBitmap() {
// TODO(mattcarroll): determine if this is nonull or nullable
private native Bitmap nativeGetBitmap(long nativePlatformViewId);

/**
* Notifies the Dart VM of a low memory event, or that the application is in a state such that now
* is an appropriate time to free resources, such as going to the background.
*
* <p>This is distinct from sending a SystemChannel message about low memory, which only notifies
* the running Flutter application.
*/
@UiThread
public void notifyLowMemoryWarning() {
ensureRunningOnMainThread();
ensureAttachedToNative();
nativeNotifyLowMemoryWarning();
}

private native void nativeNotifyLowMemoryWarning();

private void ensureRunningOnMainThread() {
if (Looper.myLooper() != mainLooper) {
throw new RuntimeException(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,19 @@ public void setIsolateServiceIdListener(@Nullable IsolateServiceIdListener liste
}
}

/**
* Notify the Dart VM of a low memory event, or that the application is in a state such that now
* is an appropriate time to free resources, such as going to the background.
*
* <p>This does not notify a Flutter application about memory pressure. For that, use the {@link
* SystemChannel#sendMemoryPressureWarning}.
*/
public void notifyLowMemoryWarning() {
if (flutterJNI.isAttached()) {
flutterJNI.notifyLowMemoryWarning();
}
}

/**
* Configuration options that specify which Dart entrypoint function is executed and where to find
* that entrypoint and other assets required for Dart execution.
Expand Down
1 change: 1 addition & 0 deletions shell/platform/android/io/flutter/view/FlutterView.java
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,7 @@ public void onStop() {
}

public void onMemoryPressure() {
mNativeView.getFlutterJNI().notifyLowMemoryWarning();
systemChannel.sendMemoryPressureWarning();
}

Expand Down
11 changes: 11 additions & 0 deletions shell/platform/android/platform_view_android_jni.cc
Original file line number Diff line number Diff line change
Expand Up @@ -498,6 +498,12 @@ static void InvokePlatformMessageEmptyResponseCallback(JNIEnv* env,
);
}

static void NotifyLowMemoryWarning(JNIEnv* env,
jobject obj,
jlong shell_holder) {
ANDROID_SHELL_HOLDER->NotifyLowMemoryWarning();
}

static jboolean FlutterTextUtilsIsEmoji(JNIEnv* env,
jobject obj,
jint codePoint) {
Expand Down Expand Up @@ -568,6 +574,11 @@ bool RegisterApi(JNIEnv* env) {
.fnPtr = reinterpret_cast<void*>(
&InvokePlatformMessageEmptyResponseCallback),
},
{
.name = "nativeNotifyLowMemoryWarning",
.signature = "()V",
.fnPtr = reinterpret_cast<void*>(&NotifyLowMemoryWarning),
},

// Start of methods from FlutterView
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package io.flutter.embedding.android;

import static android.content.ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW;
import static android.content.ComponentCallbacks2.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.mockito.Matchers.any;
Expand Down Expand Up @@ -442,7 +442,7 @@ public void itForwardsOnUserLeaveHintToFlutterEngine() {
}

@Test
public void itSendsMessageOverSystemChannelWhenToldToTrimMemory() {
public void itNotifiesDartExecutorAndSendsMessageOverSystemChannelWhenToldToTrimMemory() {
// Create the real object that we're testing.
FlutterActivityAndFragmentDelegate delegate = new FlutterActivityAndFragmentDelegate(mockHost);

Expand All @@ -451,14 +451,21 @@ public void itSendsMessageOverSystemChannelWhenToldToTrimMemory() {
delegate.onAttach(RuntimeEnvironment.application);
Copy link
Member

Choose a reason for hiding this comment

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

nit: you should change the test name now

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done


// Emulate the host and call the method that we expect to be forwarded.
delegate.onTrimMemory(TRIM_MEMORY_RUNNING_MODERATE);
delegate.onTrimMemory(TRIM_MEMORY_RUNNING_LOW);
delegate.onTrimMemory(TRIM_MEMORY_RUNNING_CRITICAL);
delegate.onTrimMemory(TRIM_MEMORY_BACKGROUND);
delegate.onTrimMemory(TRIM_MEMORY_COMPLETE);
delegate.onTrimMemory(TRIM_MEMORY_MODERATE);
delegate.onTrimMemory(TRIM_MEMORY_UI_HIDDEN);

// Verify that the call was forwarded to the engine.
verify(mockFlutterEngine.getDartExecutor(), times(7)).notifyLowMemoryWarning();
verify(mockFlutterEngine.getSystemChannel(), times(1)).sendMemoryPressureWarning();
}

@Test
public void itSendsMessageOverSystemChannelWhenInformedOfLowMemory() {
public void itNotifiesDartExecutorAndSendsMessageOverSystemChannelWhenInformedOfLowMemory() {
// Create the real object that we're testing.
FlutterActivityAndFragmentDelegate delegate = new FlutterActivityAndFragmentDelegate(mockHost);

Expand All @@ -470,6 +477,7 @@ public void itSendsMessageOverSystemChannelWhenInformedOfLowMemory() {
delegate.onLowMemory();
Copy link
Member

Choose a reason for hiding this comment

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

ditto

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done


// Verify that the call was forwarded to the engine.
verify(mockFlutterEngine.getDartExecutor(), times(1)).notifyLowMemoryWarning();
verify(mockFlutterEngine.getSystemChannel(), times(1)).sendMemoryPressureWarning();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.content.res.AssetManager;
import io.flutter.embedding.engine.FlutterJNI;
Expand Down Expand Up @@ -38,4 +39,15 @@ public void itSendsBinaryMessages() {
verify(fakeFlutterJni, times(1))
.dispatchPlatformMessage(eq("fake_channel"), eq(fakeMessage), anyInt(), anyInt());
}

@Test
public void itNotifiesLowMemoryWarning() {
FlutterJNI mockFlutterJNI = mock(FlutterJNI.class);
when(mockFlutterJNI.isAttached()).thenReturn(true);

DartExecutor dartExecutor = new DartExecutor(mockFlutterJNI, mock(AssetManager.class));
dartExecutor.notifyLowMemoryWarning();
;
Copy link
Member

Choose a reason for hiding this comment

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

fyi stray semicolon

verify(mockFlutterJNI, times(1)).notifyLowMemoryWarning();
}
}