mirror of
https://github.com/yuga-hashimoto/openclaw-assistant.git
synced 2026-08-14 08:47:12 +00:00
🔄 Upstream Parity: Fix Bitmap memory leaks in CanvasController snapshots (#412)
Wraps snapshotPngBase64/snapshotBase64 in nested try/finally blocks to ensure Bitmap.recycle() is always called, preventing native memory leaks on each snapshot invocation.
This commit is contained in:
@@ -236,39 +236,55 @@ class CanvasController {
|
||||
withContext(Dispatchers.Main) {
|
||||
val wv = webView ?: throw IllegalStateException("no webview")
|
||||
val bmp = wv.captureBitmap()
|
||||
val scaled =
|
||||
if (maxWidth != null && maxWidth > 0 && bmp.width > maxWidth) {
|
||||
val h = (bmp.height.toDouble() * (maxWidth.toDouble() / bmp.width.toDouble())).toInt().coerceAtLeast(1)
|
||||
bmp.scale(maxWidth, h)
|
||||
} else {
|
||||
bmp
|
||||
}
|
||||
try {
|
||||
val scaled =
|
||||
if (maxWidth != null && maxWidth > 0 && bmp.width > maxWidth) {
|
||||
val h = (bmp.height.toDouble() * (maxWidth.toDouble() / bmp.width.toDouble())).toInt().coerceAtLeast(1)
|
||||
bmp.scale(maxWidth, h)
|
||||
} else {
|
||||
bmp
|
||||
}
|
||||
|
||||
val out = ByteArrayOutputStream()
|
||||
scaled.compress(Bitmap.CompressFormat.PNG, 100, out)
|
||||
Base64.encodeToString(out.toByteArray(), Base64.NO_WRAP)
|
||||
try {
|
||||
val out = ByteArrayOutputStream()
|
||||
scaled.compress(Bitmap.CompressFormat.PNG, 100, out)
|
||||
Base64.encodeToString(out.toByteArray(), Base64.NO_WRAP)
|
||||
} finally {
|
||||
if (scaled !== bmp) scaled.recycle()
|
||||
}
|
||||
} finally {
|
||||
bmp.recycle()
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun snapshotBase64(format: SnapshotFormat, quality: Double?, maxWidth: Int?): String =
|
||||
withContext(Dispatchers.Main) {
|
||||
val wv = webView ?: throw IllegalStateException("no webview")
|
||||
val bmp = wv.captureBitmap()
|
||||
val scaled =
|
||||
if (maxWidth != null && maxWidth > 0 && bmp.width > maxWidth) {
|
||||
val h = (bmp.height.toDouble() * (maxWidth.toDouble() / bmp.width.toDouble())).toInt().coerceAtLeast(1)
|
||||
bmp.scale(maxWidth, h)
|
||||
} else {
|
||||
bmp
|
||||
}
|
||||
try {
|
||||
val scaled =
|
||||
if (maxWidth != null && maxWidth > 0 && bmp.width > maxWidth) {
|
||||
val h = (bmp.height.toDouble() * (maxWidth.toDouble() / bmp.width.toDouble())).toInt().coerceAtLeast(1)
|
||||
bmp.scale(maxWidth, h)
|
||||
} else {
|
||||
bmp
|
||||
}
|
||||
|
||||
val out = ByteArrayOutputStream()
|
||||
val (compressFormat, compressQuality) =
|
||||
when (format) {
|
||||
SnapshotFormat.Png -> Bitmap.CompressFormat.PNG to 100
|
||||
SnapshotFormat.Jpeg -> Bitmap.CompressFormat.JPEG to clampJpegQuality(quality)
|
||||
try {
|
||||
val out = ByteArrayOutputStream()
|
||||
val (compressFormat, compressQuality) =
|
||||
when (format) {
|
||||
SnapshotFormat.Png -> Bitmap.CompressFormat.PNG to 100
|
||||
SnapshotFormat.Jpeg -> Bitmap.CompressFormat.JPEG to clampJpegQuality(quality)
|
||||
}
|
||||
scaled.compress(compressFormat, compressQuality, out)
|
||||
Base64.encodeToString(out.toByteArray(), Base64.NO_WRAP)
|
||||
} finally {
|
||||
if (scaled !== bmp) scaled.recycle()
|
||||
}
|
||||
scaled.compress(compressFormat, compressQuality, out)
|
||||
Base64.encodeToString(out.toByteArray(), Base64.NO_WRAP)
|
||||
} finally {
|
||||
bmp.recycle()
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun WebView.captureBitmap(): Bitmap =
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
1. **Explore the upstream repo**
|
||||
- Use `git clone` or fetch to investigate recent commits in `apps/android`.
|
||||
- Find candidate commits for porting (e.g., bug fixes, memory leaks).
|
||||
- *Exploration complete*.
|
||||
|
||||
2. **Choose a suitable improvement**
|
||||
- Identified upstream commit `2909d8cd12` ("Android: fix Bitmap memory leaks in CanvasController snapshots").
|
||||
- This prevents memory leaks caused by not recycling Bitmaps (`bmp` and `scaled`) during `snapshotPngBase64()` and `snapshotBase64()` in `CanvasController.kt`.
|
||||
- Verified that `CanvasController.kt` in this repo has the exact same leak.
|
||||
|
||||
3. **Port the improvement**
|
||||
- Modify `app/src/main/java/com/openclaw/assistant/node/CanvasController.kt`.
|
||||
- Update `snapshotPngBase64()` and `snapshotBase64()` to wrap operations in `try...finally` blocks, ensuring `bmp` and `scaled` are correctly recycled if they differ.
|
||||
- Use `replace_with_git_merge_diff` to modify the file.
|
||||
|
||||
4. **Run Native Validation Commands**
|
||||
- Run `app:lintStandardDebug` and `app:testStandardDebugUnitTest` with the `./gradlew` command to verify compilation and prevent regressions.
|
||||
|
||||
5. **Complete pre-commit steps to ensure proper testing, verification, review, and reflection are done.**
|
||||
- Run `pre_commit_instructions`.
|
||||
|
||||
6. **Submit PR**
|
||||
- Use the `submit` tool to create a PR named `🔄 Upstream Parity: Fix Bitmap memory leaks in CanvasController snapshots` detailing the source, why, adaptation, and verification.
|
||||
Reference in New Issue
Block a user