我正在使用虚拟显示器从 Android 模拟器中截取屏幕截图,我注意到surfaceflinger的内存无限增长(这可以在顶级程序中看到)并且模拟器在一段时间后停止工作。在真正的 Android 设备上一切正常:内存增加 5Mb,然后被清除。但是在 GenyMotion 和 LDPlayer 等模拟器上,surfaceflinger 工作异常。我尝试了两种不同的创建 VirtualDisplay 的方法:通过 1)ImageReader 或 2)GLES:
- 图像阅读器
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
)
- 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 运行良好,但我无法将任何用户友好的模拟器升级到这个版本