Android Kakao Maps SDK 2.15.2] Galaxy M15 5G에서 GLSurfaceView.surfaceCreated() ANR 반복 발생 – AssetManager 잠금 대기 관련 기술지원 요청

안녕하세요.

현재 Flutter기반 Android앱에서 Kakao Maps SDK v2를 네이티브 PlatformView(AndroidView)방식으로 사용하고 있습니다.

실제 서비스 중인 앱에서 특정 단말기(Samsung Galaxy M15 5G)를 중심으로 동일한 유형의 ANR이 반복적으로 발생하여 기술지원을 요청드립니다 .

해당 앱은 수렵인의 실시간 위치 확인 및 근접경보 기능을 제공하는 안전 관련 시스템으로, ANR발생 시 현장 사용에 문제가 발생할 수 있어 원인 규명과 안정적인 해결 방법이 필요한 상황입니다.

1.개발 및 실행 환경

-앱 패키지: com.kowildlife.app

-개발 환경: Flutter 3.35.6 / Android Kotlin

- Kakao Maps SDK: 2.15. 2

-지도 구현: Flutter AndroidView + Native Kakao MapVi ew

- ANR발생 단말기: Samsung Galaxy M15 5G

- Google Play Console발생 버전 코드: 222

- GPU관련 라이브러리: Mali (`libGLES_mali .so`)

-지도 생명주기: Activity의 onResume/onPause와 MapView.resume()/pause()연동

2. ANR현상

Google Play Console에서 동일한 유형의 ANR이 반복적으로 수집되고 있습니다.

ANR발생 시 Android메인 스레드는 다음 위치에서 대기합니다.

```text

“main” tid= 1 Waiting

java.lang.O bject.wait

com.kakao.vectormap.graphics.gl.GLSurfaceView$GLThread.sur faceCreated

com.kakao.vectormap.graphics.gl.GLSurfaceView.su rfaceCreated

android.view.SurfaceView. updateSurface

android.view.ViewRootImpl.per formTr aversals

```

동시에 카카오맵 GLThread는 다음 위치에서 잠금 대기 상태에 있습니 다.

```text

“GLThread 284” tid=68 Native

NonPI::M utexLockWithTimeout

std::mutex::lock

AAssetManager_open

kakao::application::android::AssetAccessor Android::getAssetChunk

kakao::content::asset::AssetM anager::_loadStringData

kakao::content::asset::AssetMa nager::getStringResource

kakao::content::reader::JsonTypeReaderToVie wResult::_makeTechniqueGL

kakao::content::As yncContentManager::execute

ka kao::app::AppEngine::render

com.kakao.vectormap.intern al.GLM apRenderer.onDrawFrame

```

메인 스레드는 GLThread의 Surface생성 처리를 기다리는 반면, GLThread는 카카오맵 내부 렌더링 리소스를 읽는 과정에서 `AAssetManager_open ()`의 뮤텍스 획득을 기다리는 것으로 나타납니다.

다만 해당 잠금의 점유 스레드는 현재 덤프에서 확인되지 않아 정확한 교착상태 여부는 판단하지 못하고 있습니다.

3.현재 지도 구현 방식

- `MapView.start()`중복 실행 방지

- `MapView.setFinishManually(true)`적용

- `MapView.pause()/resume()`중복 호출 방지

- Flutter화면 전환 시 지도 객체의 불필요한 재생성 방지

-지도 미표시 또는 오프라인 상태에서 렌더링 중지 요청

- GPS위치 갱신과 지도 렌더링 제어는 별도로 운영

여러 차례 생명주기 및 지도 표시 방식을 점검했으나 ANR이 재발하고 있습니다.

4.확인 요청 사 항

① 카카오맵 SDK내부 잠금 관련

`GLSurfaceView$GLThread.surfaceCreated()`에서 메인 스레드가 대기하는 동안 GLThread가 `AAssetManager_open()`에서 대기하는 현상이 SDK내부의 알려진 문제인지 확 인 부탁드립니다.

② 특정 단말기 호환성

Samsung Galaxy M15 5G의 MediaTek/Mali GPU 환경에서 동일하거나 유사한 ANR사례가 있는지 문의드립니다.

③ MapView생명주기

Flutter PlatformView내부에서 `MapView`를 사용할 때 `start()`, `pause()`, `resume()`, `finish()`및 `setFinishManually(true)`를 안 정적으로 관리하기 위한 공식 권장 방식이 있는지 확인 부탁드립니다.

④ SDK버전 및 해결 방법

현재 사용 중인 2.15.2버전에서 해당 문제가 개선된 다른 SDK버전이 있는 지,또는 공식적으로 권장하는 우회 방 법이 있는지 안내 부탁드립니다.

⑤ 추가 진단 자료

정확한 원인 분석을 위해 ANR 덤프 외에 필요한 로그 또는 추가 진단 방법이 있다면 알려주시기 바랍니다.

현재 실서비스 중이므로 충분한 근거 없이 지도 생명주기나 렌더링 구조를 변경하기 어려운 상황입니다.

가능하시다면 첨부된 ANR스레드 덤프를 SDK 개발 담당 부서에서 검 토하여 원인과 해결 방향을 안내해 주시면 감사하겠습니다.

감사합니다.

@kelly.ka

안녕하세요,
위 문의 건 혹시 도움 주실 수 있는 부분이 있을까요

안녕하세요. 자세히 ANR 제보해 주셔서 감사합니다. 현재까지는 위와 같은 문제로 보고 된 이슈는 없습니다. 아무래도, 앱 마다 지도의 사용패턴 및 라이프사이클이 다르기 때문에 같은 SDK/디바이스라 하더라도 문제 발생 여부가 다릅니다.

올려주신 내용만 놓고 유추해봤을 땐,

  • AAssetManager_open은 프로세스 전역 뮤텍스를 사용하므로, Flutter 엔진 및 다른 PlatformView 인스턴스가 동시에 asset을 읽는 상황에서의 경합으로 보여집니다. (Flutter 엔진 자체도 AAssetManager를 사용)
  • 그리고, Samsung Galaxy M15 5G / Mali/MediaTek 저사양 디바이스에서 asset I/O가 느려 lock 보유 시간이 길어지면서 ANR 이 발생하는 걸로 추정됩니다.

하지만, 정확한 원인 판단은 아래의 첨부파일 및 답변을 추가로 주시면 좋을 것 같습니다.

  1. 완전한 ANR traces.txt (모든 스레드 포함 — 현재 덤프에 lock holder 스레드가 누락됨)
  2. ANR 시에 Flutter 엔진 스레드 상태 (특히 1.ui, 1.raster 스레드가 AAssetManager를 점유 중인지 확인 필요)
  3. ANR 발생 직전 지도 재생성 횟수 (PlatformView dispose/create 로그)
  4. Flutter의 PlatformView 생성할 때 렌더링 모드 (AndroidView 위젯 사용인지 PlatformViewLink 인지)
    1. AndroidView 위젯 (선언형)
    2. PlatformViewLink + initSurfaceAndroidView
    3. PlatformViewLink + initExpensiveAndroidView (Hybrid Composition)
    4. PlatformViewLink + initAndroidView (Virtual Display)

추가로, 앱 시작 직후 Flutter 엔진 초기 로딩과 지도 리소스 로딩이 겹치면서 asset lock 경합으로 인한 문제인지 확인하기 위해 아래와 같이 지도 생성을 살짝 지연시켰을 때 ANR 발생 추이를 확인해 주시면 좋을 것 같습니다.

WidgetsBinding.instance.addPostFrameCallback((_) {
        // 추가로 짧은 delay를 주고 MapView 생성
        Future.delayed(const Duration(milliseconds: 300), () {
        setState(() => _showMap = true);
    });
});