Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

A memory leak occurs when using SurfaceView together with AndroidView #118384

Open
add022 opened this issue Jan 12, 2023 · 12 comments
Open

A memory leak occurs when using SurfaceView together with AndroidView #118384

add022 opened this issue Jan 12, 2023 · 12 comments
Labels
a: platform-views Embedding Android/iOS views in Flutter apps c: performance Relates to speed or footprint issues (see "perf:" labels) found in release: 3.3 Found to occur in 3.3 found in release: 3.7 Found to occur in 3.7 has reproducible steps The issue has been confirmed reproducible and is ready to work on P2 Important issues not at the top of the work list perf: memory Performance issues related to memory platform-android Android applications specifically team-android Owned by Android platform team triaged-android Triaged by Android platform team

Comments

@add022
Copy link

add022 commented Jan 12, 2023

Details

There seems to be a memory leak when using AndroidView together with SurfaceView at native side.

I've created simple app which can demonstrate the issue. It displays AndroidView which could use SurfaceView or TextureView to display native content.
App is able to toggle AndroidView visibility.
The leak occurs when AndroidView is removed from widget tree and then recreated multiple times during app operation.
Sources: https://github.com/add022/flutter_native_view_sample_java

Here is sample screenshot from Profiler when app is using SurfaceView and toggling AndroidView visibility multiple times. Memory constantly growing, GC is also not able to reclaim allocated memory.
image
I've used SurfaceHolder's callbacks to track surface lifecycle and it seems that surfaceDestroyed() seems to be not called when AndroidView is removed from widget tree. That may be some clue.

On the other side when TextureView is used with the same scenario the leak seems to be not visible, and memory seems to be correclty reclaimed by GC:
image
I've also examined the lifecycle of TextureView using TextureView.SurfaceTextureListener.
In this case the onSurfaceTextureDestroyed seems to be called every time AndroidView is removed from widget tree.

Issue was oserved on Flutter 3.3.9 and also verified that it still exists in 3.7.0-1.4.pre.

Target Platform: Android
Target OS version/browser: Android 13(and others)
Devices: Samsung S22+(and others)

Logs

Logs

Here is some StrictMode violation which can be observed after GC:

2023-01-12 14:26:48.017 20071-20092 StrictMode              com...utter_native_view_sample_java  D  StrictMode policy violation: android.os.strictmode.LeakedClosableViolation: A resource was acquired at attached stack trace but never released. See java.io.Closeable for information on avoiding resource leaks.
                                                                                                    	at android.os.StrictMode$AndroidCloseGuardReporter.report(StrictMode.java:1986)
                                                                                                    	at dalvik.system.CloseGuard.warnIfOpen(CloseGuard.java:336)
                                                                                                    	at android.view.Surface.finalize(Surface.java:310)
                                                                                                    	at java.lang.Daemons$FinalizerDaemon.doFinalize(Daemons.java:319)
                                                                                                    	at java.lang.Daemons$FinalizerDaemon.runInternal(Daemons.java:306)
                                                                                                    	at java.lang.Daemons$Daemon.run(Daemons.java:140)
                                                                                                    	at java.lang.Thread.run(Thread.java:1012)
                                                                                                    Caused by: java.lang.Throwable: Explicit termination method 'Surface.release' not called
                                                                                                    	at dalvik.system.CloseGuard.openWithCallSite(CloseGuard.java:288)
                                                                                                    	at dalvik.system.CloseGuard.open(CloseGuard.java:257)
                                                                                                    	at android.view.Surface.setNativeObjectLocked(Surface.java:760)
                                                                                                    	at android.view.Surface.<init>(Surface.java:294)
                                                                                                    	at io.flutter.plugin.platform.VirtualDisplayController.create(VirtualDisplayController.java:53)
                                                                                                    	at io.flutter.plugin.platform.PlatformViewsController$1.configureForVirtualDisplay(PlatformViewsController.java:541)
                                                                                                    	at io.flutter.plugin.platform.PlatformViewsController$1.createForTextureLayer(PlatformViewsController.java:219)
                                                                                                    	at io.flutter.embedding.engine.systemchannels.PlatformViewsChannel$1.create(PlatformViewsChannel.java:128)
                                                                                                    	at io.flutter.embedding.engine.systemchannels.PlatformViewsChannel$1.onMethodCall(PlatformViewsChannel.java:55)
                                                                                                    	at io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler.onMessage(MethodChannel.java:258)
                                                                                                    	at io.flutter.embedding.engine.dart.DartMessenger.invokeHandler(DartMessenger.java:295)
                                                                                                    	at io.flutter.embedding.engine.dart.DartMessenger.lambda$dispatchMessageToQueue$0$io-flutter-embedding-engine-dart-DartMessenger(DartMessenger.java:322)
                                                                                                    	at io.flutter.embedding.engine.dart.DartMessenger$$ExternalSyntheticLambda0.run(Unknown Source:12)
                                                                                                    	at android.os.Handler.handleCallback(Handler.java:942)
                                                                                                    	at android.os.Handler.dispatchMessage(Handler.java:99)
                                                                                                    	at android.os.Looper.loopOnce(Looper.java:226)
                                                                                                    	at android.os.Looper.loop(Looper.java:313)
                                                                                                    	at android.app.ActivityThread.main(ActivityThread.java:8741)
                                                                                                    	at java.lang.reflect.Method.invoke(Native Method)
                                                                                                    	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:571)
                                                                                                    	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1067)

Also following logs about abandoned buffers seems to appear after GC execution:

2023-01-12 14:26:49.423 20071-20238 BufferQueueProducer     com...utter_native_view_sample_java  E  [SurfaceTexture-0-20071-0](id:4e6700000002,api:1,p:1138,c:20071) dequeueBuffer: BufferQueue has been abandoned
2023-01-12 14:26:49.423 20071-20238 BufferQueueProducer     com...utter_native_view_sample_java  E  [SurfaceTexture-0-20071-1](id:4e6700000005,api:1,p:1138,c:20071) dequeueBuffer: BufferQueue has been abandoned
2023-01-12 14:26:49.423 20071-20238 BufferQueueProducer     com...utter_native_view_sample_java  E  [SurfaceTexture-0-20071-2](id:4e6700000008,api:1,p:1138,c:20071) dequeueBuffer: BufferQueue has been abandoned
2023-01-12 14:26:49.423 20071-20238 BufferQueueProducer     com...utter_native_view_sample_java  E  [SurfaceTexture-0-20071-3](id:4e670000000b,api:1,p:1138,c:20071) dequeueBuffer: BufferQueue has been abandoned
2023-01-12 14:26:49.423 20071-20238 BufferQueueProducer     com...utter_native_view_sample_java  E  [SurfaceTexture-0-20071-4](id:4e670000000e,api:1,p:1138,c:20071) dequeueBuffer: BufferQueue has been abandoned
2023-01-12 14:26:49.423 20071-20238 BufferQueueProducer     com...utter_native_view_sample_java  E  [SurfaceTexture-0-20071-5](id:4e6700000011,api:1,p:1138,c:20071) dequeueBuffer: BufferQueue has been abandoned
2023-01-12 14:26:49.424 20071-20238 BufferQueueProducer     com...utter_native_view_sample_java  E  [SurfaceTexture-0-20071-6](id:4e6700000014,api:1,p:1138,c:20071) dequeueBuffer: BufferQueue has been abandoned
2023-01-12 14:26:49.424 20071-20238 BufferQueueProducer     com...utter_native_view_sample_java  E  [SurfaceTexture-0-20071-7](id:4e6700000017,api:1,p:1138,c:20071) dequeueBuffer: BufferQueue has been abandoned

Flutter doctor:

[✓] Flutter (Channel stable, 3.3.9, on macOS 12.5.1 21G83 darwin-x64, locale en-PL)
    • Flutter version 3.3.9 on channel stable at /Users/domin/fvm/versions/3.3.9
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision b8f7f1f986 (7 weeks ago), 2022-11-23 06:43:51 +0900
    • Engine revision 8f2221fbef
    • Dart version 2.18.5
    • DevTools version 2.15.0

[!] Android toolchain - develop for Android devices (Android SDK version 30.0.3)
    • Android SDK at /Users/domin/Library/Android/sdk
    ✗ cmdline-tools component is missing
      Run `path/to/sdkmanager --install "cmdline-tools;latest"`
      See https://developer.android.com/studio/command-line for more details.
    ✗ Android license status unknown.
      Run `flutter doctor --android-licenses` to accept the SDK licenses.
      See https://flutter.dev/docs/get-started/install/macos#android-setup for more details.

[✓] Xcode - develop for iOS and macOS (Xcode 14.1)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Build 14B47
    • CocoaPods version 1.11.2

[✓] Chrome - develop for the web
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 2021.3)
    • Android Studio at /Applications/Android Studio.app/Contents
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 11.0.13+0-b1751.21-8125866)

[✓] VS Code (version 1.74.2)
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension version 3.56.0

[✓] Connected device (3 available)
    • SM S906B (mobile) • RFCTA01WFRA • android-arm64  • Android 13 (API 33)
    • macOS (desktop)   • macos       • darwin-x64     • macOS 12.5.1 21G83 darwin-x64
    • Chrome (web)      • chrome      • web-javascript • Google Chrome 109.0.5414.87

[✓] HTTP Host Availability
    • All required HTTP hosts are available

! Doctor found issues in 1 category.

@add022 add022 added the from: performance template Issues created via a performance issue template label Jan 12, 2023
@darshankawar darshankawar removed the from: performance template Issues created via a performance issue template label Jan 12, 2023
@add022 add022 changed the title A memory occurs leak when using SurfaceView together with AndroidView A memory leak occurs when using SurfaceView together with AndroidView Jan 12, 2023
@darshankawar darshankawar added the in triage Presently being triaged by the triage team label Jan 13, 2023
@darshankawar
Copy link
Member

Thanks for the report and details around it.
It seems that SurfaceTexture is a stream of frame and rendering using this class will force the device to do a copy on each render and on top of that this use case is using SurfaceView and AndroidView together which could be leading to memory spike.
Using the code sample provided and running on Samsung S10, seeing the same behavior as reported.

code sample
import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.lime,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  bool _showNativeView = false;
  bool _useTexture = false;

  void _toggleNativeView(bool value) => setState(() => _showNativeView = value);
  void _toggleTextureInUse(bool value) => setState(() => _useTexture = value);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      // backgroundColor: Colors.red,
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.start,
          children: <Widget>[
            SwitchListTile(
              title: const Text(
                'Toggle native view',
              ),
              value: _showNativeView,
              onChanged: _toggleNativeView,
            ),
            SwitchListTile(
              title: const Text(
                'Use texture',
              ),
              value: _useTexture,
              onChanged: _toggleTextureInUse,
            ),
            AspectRatio(aspectRatio: 1, child: _buildNativeViewWidget()),
          ],
        ),
      ),
    );
  }

  Widget _buildNativeViewWidget() {
    if (_showNativeView) {
      return Container(
        decoration: BoxDecoration(border: Border.all(color: Colors.blueAccent)),
        child: AndroidView(
            viewType:
                _useTexture ? 'texture_native_view' : 'surface_native_view'),
      );
    } else {
      return const SizedBox.expand();
    }
  }
}

stable, master flutter doctor -v
[✓] Flutter (Channel stable, 3.3.10, on macOS 12.2.1 21D62 darwin-x64, locale
    en-GB)
    • Flutter version 3.3.10 on channel stable at
      /Users/dhs/documents/fluttersdk/flutter
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision 135454af32 (15 hours ago), 2022-12-15 07:36:55 -0800
    • Engine revision 3316dd8728
    • Dart version 2.18.6
    • DevTools version 2.15.0

[!] Xcode - develop for iOS and macOS (Xcode 12.3)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    ! Flutter recommends a minimum Xcode version of 13.
      Download the latest version or update via the Mac App Store.
    • CocoaPods version 1.11.2

[✓] Chrome - develop for the web
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] VS Code (version 1.62.0)
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension version 3.21.0

[✓] Connected device (5 available)
    • SM G975F (mobile)       • RZ8M802WY0X • android-arm64   • Android 11 (API 30)
    • Darshan's iphone (mobile)  • 21150b119064aecc249dfcfe05e259197461ce23 •
      ios            • iOS 14.4.1 18D61
    • iPhone 12 Pro Max (mobile) • A5473606-0213-4FD8-BA16-553433949729     •
      ios            • com.apple.CoreSimulator.SimRuntime.iOS-14-3 (simulator)
    • macOS (desktop)            • macos                                    •
      darwin-x64     • Mac OS X 10.15.4 19E2269 darwin-x64
    • Chrome (web)               • chrome                                   •
      web-javascript • Google Chrome 98.0.4758.80

[✓] HTTP Host Availability
    • All required HTTP hosts are available

! Doctor found issues in 1 category.

[[!] Flutter (Channel master, 3.7.0-20.0.pre.28, on macOS 12.2.1 21D62
    darwin-x64, locale en-GB)
    • Flutter version 3.7.0-20.0.pre.28 on channel master at
      /Users/dhs/documents/fluttersdk/flutter
    ! Warning: `flutter` on your path resolves to
      /Users/dhs/Documents/Fluttersdk/flutter/bin/flutter, which is not inside
      your current Flutter SDK checkout at
      /Users/dhs/documents/fluttersdk/flutter. Consider adding
      /Users/dhs/documents/fluttersdk/flutter/bin to the front of your path.
    ! Warning: `dart` on your path resolves to
      /Users/dhs/Documents/Fluttersdk/flutter/bin/dart, which is not inside your
      current Flutter SDK checkout at /Users/dhs/documents/fluttersdk/flutter.
      Consider adding /Users/dhs/documents/fluttersdk/flutter/bin to the front
      of your path.
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision 59d737e647 (81 minutes ago), 2023-01-12 22:28:25 -0500
    • Engine revision 99509a7e42
    • Dart version 3.0.0 (build 3.0.0-119.0.dev)
    • DevTools version 2.20.0
    • If those were intentional, you can disregard the above warnings; however
      it is recommended to use "git" directly to perform update checks and
      upgrades.

[!] Xcode - develop for iOS and macOS (Xcode 12.3)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    ! Flutter recommends a minimum Xcode version of 13.
      Download the latest version or update via the Mac App Store.
    • CocoaPods version 1.11.2

[✓] Chrome - develop for the web
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] VS Code (version 1.62.0)
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension version 3.21.0

[✓] Connected device (5 available)
    • SM G975F (mobile)       • RZ8M802WY0X • android-arm64   • Android 11 (API 30)
    • Darshan's iphone (mobile)  • 21150b119064aecc249dfcfe05e259197461ce23 •
      ios            • iOS 14.4.1 18D61
    • iPhone 12 Pro Max (mobile) • A5473606-0213-4FD8-BA16-553433949729     •
      ios            • com.apple.CoreSimulator.SimRuntime.iOS-14-3 (simulator)
    • macOS (desktop)            • macos                                    •
      darwin-x64     • Mac OS X 10.15.4 19E2269 darwin-x64
    • Chrome (web)               • chrome                                   •
      web-javascript • Google Chrome 98.0.4758.80

[✓] HTTP Host Availability
    • All required HTTP hosts are available

! Doctor found issues in 1 category.



@darshankawar darshankawar added platform-android Android applications specifically c: performance Relates to speed or footprint issues (see "perf:" labels) perf: memory Performance issues related to memory has reproducible steps The issue has been confirmed reproducible and is ready to work on found in release: 3.3 Found to occur in 3.3 found in release: 3.7 Found to occur in 3.7 a: platform-views Embedding Android/iOS views in Flutter apps and removed in triage Presently being triaged by the triage team labels Jan 13, 2023
@GaryQian GaryQian added the P2 Important issues not at the top of the work list label Jan 19, 2023
@ygit
Copy link

ygit commented Feb 26, 2023

Any updates on when a fix for this will be released?

@varunvasista
Copy link

When it will be fixed ?

@ArkeshGKalathiya
Copy link

Same issue here while integrating cocos2d-x game engine with flutter, destroying and re-adding native views leads to memory leak ( each time 5-10mb jump ).

@stefanschaller

This comment was marked as duplicate.

@ArkeshGKalathiya
Copy link

Mine was related to stale cocos2dx view instance.

@flutter-triage-bot flutter-triage-bot bot added team-android Owned by Android platform team triaged-android Triaged by Android platform team labels Jul 8, 2023
@limingchina
Copy link

limingchina commented Jul 23, 2023

I've modified the code from the repository(https://github.com/add022/flutter_native_view_sample_java) of the report so that it automatically switch the native view's visibility. Please refer to diff.txt.

This way, one can use memory profiler to see how the memory grows. Even using TextureView, the memory still grows constantly overtime. I even tried to replace the SurfaceView with a simple TextView to display a few text, I still can see the constant growth. That might be additional leak somewhere. If it's confirmed to happen for general usage, I think the priority should be raised.

The following is my simple native view containing a TextView:

package com.example.hello_world;
import android.content.Context;
import android.graphics.Color;
import android.view.View;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import java.util.Map;

import io.flutter.plugin.platform.PlatformView;

public class NativeTextView implements PlatformView {
    private TextView textView;
    NativeTextView(@NonNull Context context, int id, @Nullable Map<String, Object> creationParams) {
        textView = new TextView(context);
        textView.setTextSize(72);
        textView.setBackgroundColor(Color.rgb(255, 255, 255));
        textView.setText("Rendered on a native Android view (id: " + id + ")");
    }

    @NonNull
    @Override
    public View getView() {
        return textView;
    }

    @Override
    public void dispose() {
    }
}

@zilong-zZ
Copy link

When it will be fixed ? urgent!!

@ankiimation

This comment was marked as duplicate.

@favazHF

This comment was marked as duplicate.

@yunikkk
Copy link

yunikkk commented Mar 1, 2024

@ankiimation
Copy link

any update?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
a: platform-views Embedding Android/iOS views in Flutter apps c: performance Relates to speed or footprint issues (see "perf:" labels) found in release: 3.3 Found to occur in 3.3 found in release: 3.7 Found to occur in 3.7 has reproducible steps The issue has been confirmed reproducible and is ready to work on P2 Important issues not at the top of the work list perf: memory Performance issues related to memory platform-android Android applications specifically team-android Owned by Android platform team triaged-android Triaged by Android platform team
Projects
None yet
Development

No branches or pull requests