2

I am using Virtual displays to take screenshots from Android emulators and I noticed that surfaceflinger's memory has infinite growth (this can be seen in top program) and the emulator stops working after some time. On real Android devices everything works fine: the memory increases by 5Mb and then it is cleared. But on emulators such as GenyMotion and LDPlayer surfaceflinger works abnormally. I tried two different approaches of creating VirtualDisplay: through 1)ImageReader or 2)GLES:

  1. ImageReader
        val handlerThread = HandlerThread(
            javaClass.simpleName,
            Process.THREAD_PRIORITY_BACKGROUND
        ).apply { start() }
        val handler = Handler(handlerThread.looper)

        latestBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
        imageReader = ImageReader.newInstance(width, height, PixelFormat.RGBA_8888, 2)

        imageReader?.setOnImageAvailableListener(this, handler)
        val projection = mediaProjectionManager.getMediaProjection(resultCode, resultData)


        projection!!.createVirtualDisplay(
                "shooter",
                width,
                height,
                context.resources.displayMetrics.densityDpi,
                DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
                imageReader?.surface,
                null,
                null
        )
  1. GLES
        val eglCore = EglCore(null, EglCore.FLAG_TRY_GLES3)
        val consumerSurface = eglCore.createOffscreenSurface(width, height)
        eglCore.makeCurrent(consumerSurface)

        val shader = Texture2dProgram(Texture2dProgram.ProgramType.TEXTURE_EXT)
        val screen = FullFrameRect(shader);

        val textureId = screen.createTextureObject()
        val texture = SurfaceTexture(textureId, false)
        texture.setDefaultBufferSize(width, height)
        val producerSide = Surface(texture)

        val matrix = FloatArray(16)

        var closed: Boolean = false
        val buf = ByteBuffer.allocateDirect(width * height * 4)
        buf.order(ByteOrder.nativeOrder())
        val currentBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)

        texture.setOnFrameAvailableListener(object : SurfaceTexture.OnFrameAvailableListener {
            override fun onFrameAvailable(surfaceTexture: SurfaceTexture?) {
                Log.d("FRAME", "frame")

                // there may still be pending callbacks after shutting down EGL
                if (closed) return;

                eglCore.makeCurrent(consumerSurface)

                texture.updateTexImage()
                texture.getTransformMatrix(matrix)

                eglCore.makeCurrent(consumerSurface)

                // draw the image to framebuffer object
                screen.drawFrame(textureId, matrix)
                eglCore.swapBuffers(consumerSurface)

                buf.rewind()
                GLES20.glReadPixels(0, 0, width, height, GLES10.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, buf)

                buf.rewind()
                currentBitmap.copyPixelsFromBuffer(buf)

            }
        })
        val mediaProjectionManager = context.getSystemService(Context.MEDIA_PROJECTION_SERVICE) as MediaProjectionManager
        val projection = mediaProjectionManager.getMediaProjection(resultCode, resultData)
        projection!!.createVirtualDisplay(
            "shooter",
            width,
            height,
            context.resources.displayMetrics.densityDpi,
            DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
            producerSide,
            null,
            null
        )

There are grafica classes at the 2-nd solution.

In LDPlayer's logcat I can see such messages after screenshooter start in both cases: EGL adreno: eglMakeCurrent: 0xc77d6480: ver 3 1 (tinfo 0xc77cb700)

And there is such Low Memory log after about an hour app work with 1Gb of RAM:

05-04 12:55:00.464  1181  1181 D EGL_adreno: eglMakeCurrent: 0xc77d6480: ver 3 1 (tinfo 0xc77cb720)
05-04 12:55:00.494  1303  1652 D GraphicsStats: Buffer count: 2
05-04 12:55:00.495  1181  1181 D EGL_adreno: eglMakeCurrent: 0xc77d6480: ver 3 1 (tinfo 0xc77cb720)
05-04 12:55:00.495  1303  1781 I VirtualDisplayAdapter: Virtual display device released because application token died: com.myapp
05-04 12:55:00.495  1303  1652 I ActivityManager: Process com.myapp (pid 1998) has died
05-04 12:55:00.495  1303  1652 D ActivityManager: cleanUpApplicationRecord -- 1998
05-04 12:55:00.495  1181  1181 E Surface : queueBuffer: error queuing buffer to SurfaceTexture, -32
05-04 12:55:00.495  1181  1181 E EGL_adreno: tid 1181: swapBuffers(577): error 0x300d (EGL_BAD_SURFACE)
05-04 12:55:00.495  1181  1181 E DisplayDevice: eglSwapBuffers(0x1, 0xc60ff720) failed with 0x0000300d
05-04 12:55:00.496  1181  1181 D EGL_adreno: eglMakeCurrent: 0xc77d6480: ver 3 1 (tinfo 0xc77cb720)
05-04 12:55:00.496  1303  1652 W ActivityManager: Scheduling restart of crashed service com.myapp/.presentation.service.HelpService in 1000ms
05-04 12:55:00.497  1303  1652 I ActivityManager: Process com.myapp (pid 0), (curAdj 200) has died.
05-04 12:55:00.497  1303  1652 I ActivityManager: Tell the tab as app process died as low mem.
05-04 12:55:00.498  1746  1746 W ContextImpl: Calling a method in the system process without a qualified user: android.app.ContextImpl.startService:1357 android.content.ContextWrapper.startService:613 android.content.ContextWrapper.startService:613 com.android.coreservice.CoreBroadcastReceiver.onReceive:60 android.app.ActivityThread.handleReceiver:3045
05-04 12:55:00.520  1303  1346 I DisplayManagerService: Display device removed: DisplayDeviceInfo{"shooter": uniqueId="virtual:com.myapp,10054,shooter,0", 707 x 1259, modeId 2, defaultModeId 2, supportedModes [{id=2, width=707, height=1259, fps=60.0}], colorMode 0, supportedColorModes [0], HdrCapabilities null, density 480, 480.0 x 480.0 dpi, appVsyncOff 0, presDeadline 16666666, touch NONE, rotation 0, type VIRTUAL, state ON, owner com.myapp (uid 10054), FLAG_PRESENTATION}
05-04 12:55:00.578  1181  1181 W libEGL  : EGLNativeWindowType 0xc5865808 disconnect failed
05-04 12:55:00.616  1303  2098 I ActivityManager: Low on memory:
05-04 12:55:00.616  1303  2098 I ActivityManager:   ntv   N   162240: surfaceflinger (pid 1181) native
05-04 12:55:00.616  1303  2098 I ActivityManager:   ntv   N    16987: mediaserver (pid 1194) native
05-04 12:55:00.616  1303  2098 I ActivityManager:   ntv   N    14907: media.codec (pid 1190) native
05-04 12:55:00.616  1303  2098 I ActivityManager:   ntv   N    10022: zygote (pid 1184) native
05-04 12:55:00.616  1303  2098 I ActivityManager:   ntv   N     7448: media.extractor (pid 1193) native
05-04 12:55:00.616  1303  2098 I ActivityManager:   ntv   N     2259: audioserver (pid 1185) native
05-04 12:55:00.616  1303  2098 I ActivityManager:   ntv   N     1920: logd (pid 1123) native
05-04 12:55:00.616  1303  2098 I ActivityManager:   ntv   N     1509: mediadrmserver (pid 1192) native
05-04 12:55:00.616  1303  2098 I ActivityManager:   ntv   N     1441: cameraserver (pid 1186) native
05-04 12:55:00.616  1303  2098 I ActivityManager:   ntv   N     1284: sdcard (pid 1459) native
05-04 12:55:00.616  1303  2098 I ActivityManager:   ntv   N     1227: adbd (pid 1182) native
05-04 12:55:00.616  1303  2098 I ActivityManager:   ntv   N     1141: drmserver (pid 1187) native
05-04 12:55:00.616  1303  2098 I ActivityManager:   ntv   N      994: vold (pid 1132) native
05-04 12:55:00.616  1303  2098 I ActivityManager:   ntv   N      930: netd (pid 1195) native
05-04 12:55:00.616  1303  2098 I ActivityManager:   ntv   N      909: /init (pid 1) native
05-04 12:55:00.616  1303  2098 I ActivityManager:   ntv   N      872: healthd (pid 1178) native
05-04 12:55:00.616  1303  2098 I ActivityManager:   ntv   N      706: keystore (pid 1189) native
05-04 12:55:00.616  1303  2098 I ActivityManager:   ntv   N      655: gatekeeperd (pid 1197) native
05-04 12:55:00.616  1303  2098 I ActivityManager:   ntv   N      566: lmkd (pid 1179) native
05-04 12:55:00.616  1303  2098 I ActivityManager:   ntv   N      529: ueventd (pid 891) native
05-04 12:55:00.616  1303  2098 I ActivityManager:   ntv   N      526: rild (pid 1196) native
05-04 12:55:00.616  1303  2098 I ActivityManager:   ntv   N     3506: (Other native)
05-04 12:55:00.616  1303  2098 I ActivityManager:   sys   P    48568: system (pid 1303) fixed
05-04 12:55:00.616  1303  2098 I ActivityManager:   pers  P    30288: com.android.systemui (pid 1476) fixed
05-04 12:55:00.616  1303  2098 I ActivityManager:   pers  P    16338: com.android.phone (pid 1615) fixed
05-04 12:55:00.616  1303  2098 I ActivityManager:   pers  P    10282: com.android.coreservice (pid 1746) fixed
05-04 12:55:00.616  1303  2098 I ActivityManager:   fore  T    34427: com.android.gallery3d (pid 2030) top-activity
05-04 12:55:00.616  1303  2098 I ActivityManager:   vis   SB    8551: android.ext.services (pid 1727) service
05-04 12:55:00.616  1303  2098 I ActivityManager:                        android.ext.services/.notification.Ranker<=Proc{1303:system/1000}
05-04 12:55:00.616  1303  2098 I ActivityManager:   prcp  IB   10481: com.android.inputmethod.pinyin (pid 1889) service
05-04 12:55:00.616  1303  2098 I ActivityManager:                        com.android.inputmethod.pinyin/.InputService<=Proc{1303:system/1000}
05-04 12:55:00.616  1303  2098 I ActivityManager:             391513: TOTAL
05-04 12:55:00.616  1303  2098 I ActivityManager:   MemInfo:    15,096K slab,    14,348K shmem,    12,876K vm alloc,     3,664K page tables     2,712K kernel stack
05-04 12:55:00.616  1303  2098 I ActivityManager:                  952K buffers,   126,980K cached,   111,108K mapped,    72,676K free
05-04 12:55:00.616  1303  2098 I ActivityManager:   Free RAM:    89,500K
05-04 12:55:00.616  1303  2098 I ActivityManager:   Used RAM:   440,209K
05-04 12:55:00.616  1303  2098 I ActivityManager:   Lost RAM:   -22,345K
05-04 12:55:35.664  1303  1426 D WifiNative-HAL: Failing getSupportedFeatureset because HAL isn't started
05-04 12:55:35.666  1303  1327 E BatteryStatsService: no controller energy info supplied
05-04 12:55:35.666  1303  1327 E BatteryStatsService: no controller energy info supplied
05-04 12:55:35.680  1615  1615 E PhoneInterfaceManager: [PhoneIntfMgr] queryModemActivityInfo: Empty response
05-04 12:55:35.691  1303  1327 E KernelCpuSpeedReader: Failed to read cpu-freq: /sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state (No such file or directory)
05-04 12:55:35.691  1303  1327 E BatteryStatsService: modem info is invalid: ModemActivityInfo{ mTimestamp=0 mSleepTimeMs=0 mIdleTimeMs=0 mTxTimeMs[]=[0, 0, 0, 0, 0] mRxTimeMs=0 mEnergyUsed=0}
05-04 12:56:00.006  1303  1322 I ProcessStatsService: Prepared write state in 6ms
05-04 12:56:00.008  1303  1320 I ProcessStatsService: Pruning old procstats: /data/system/procstats/state-2021-05-03-10-19-58.bin
05-04 12:56:20.628  1303  1426 D WifiStateMachine: setScanResults mScanResults.size=1
05-04 12:59:00.628  1303  1426 D WifiStateMachine: setScanResults mScanResults.size=1

I can take screenshots through file saving but it works awful. Could you please tell how can I make screenshots without memory consumption? My previous question was asked here - I did not know the cause of the problem. Also I asked the question in official Google Android community but I got no answer.

P.S. I found out that Android 10 in Genymotion works fine but I can't upgrade any user friendly emulator up to this version

  • please find your answer here https://stackoverflow.com/questions/65823544/call-release-did-not-work-after-creating-virtual-display – Jack Smother Jun 08 '21 at 16:38
  • @JackSmother but... I don't have any problem with virtual display releasing. Emulators die while my service is enabled with virtual dispplay registered. – fflush_life Jun 09 '21 at 08:55
  • have you tried bitmap pooling? – Jack Smother Jun 14 '21 at 23:04
  • @JackSmother Do you mean Glide library or something like this? I've tried bitmap pooling from Glide but that is not the case and it did not solve the problem. There is no image handling in my code so I don't create the bitmap, just registering the virtual display in the system – fflush_life Jun 15 '21 at 14:20

1 Answers1

0

I encounter same issue on genymotion android 7, surfaceflinger process can eat up to 70% memory. I have to restart machine to release memory.

Finally I switch to genymotion android 10, and this problem never occur.

bilabila
  • 973
  • 1
  • 12
  • 18
  • Yes, its a solution for development stage. But for users who work with emulators Genymotion is not very user friendly – fflush_life Feb 07 '22 at 15:41