2

我正在使用虚拟显示器从 Android 模拟器中截取屏幕截图,我注意到surfaceflinger的内存无限增长(这可以在顶级程序中看到)并且模拟器在一段时间后停止工作。在真正的 Android 设备上一切正常:内存增加 5Mb,然后被清除。但是在 GenyMotion 和 LDPlayer 等模拟器上,surfaceflinger 工作异常。我尝试了两种不同的创建 VirtualDisplay 的方法:通过 1)ImageReader 或 2)GLES:

  1. 图像阅读器
        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
        )

第二种解决方案有grafica类。

在 LDPlayer 的 logcat 中,我可以在两种情况下在屏幕截图程序启动后看到这样的消息:EGL adreno: eglMakeCurrent: 0xc77d6480: ver 3 1 (tinfo 0xc77cb700)

在使用 1Gb RAM 大约一个小时的应用程序工作后,就会出现这样的 Low Memory 日志:

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

我可以通过文件保存截取屏幕截图,但效果很糟糕。您能告诉我如何在不消耗内存的情况下制作屏幕截图吗?我之前的问题在这里被问到- 我不知道问题的原因。我也在谷歌安卓官方社区问过这个问题,但没有得到答案。

PS 我发现 Genymotion 中的 Android 10 运行良好,但我无法将任何用户友好的模拟器升级到这个版本

4

1 回答 1

0

我在 genymotion android 7 上遇到了同样的问题,surfaceflinger 进程最多可以占用 70% 的内存。我必须重新启动机器以释放内存。

最后我切换到genymotion android 10,这个问题从来没有发生过。

于 2022-02-02T09:05:39.250 回答