Make EspFlasher cancellable to prevent resource leak
Add @Volatile cancelled flag with cancel() method. Check flag at 3 checkpoints (after initial sleep, after transport setup, before each flash step) so the thread exits early and closes the USB connection in the finally block. SettingsActivity.onDestroy now calls cancel(). Reviewed in codereview.md (recommendation 3.2).
This commit is contained in:
parent
14118f4c05
commit
e116f2b493
2 changed files with 16 additions and 2 deletions
|
|
@ -25,7 +25,15 @@ class EspFlasher(private val context: Context) {
|
||||||
|
|
||||||
private val handler = Handler(Looper.getMainLooper())
|
private val handler = Handler(Looper.getMainLooper())
|
||||||
|
|
||||||
|
@Volatile
|
||||||
|
private var cancelled = false
|
||||||
|
|
||||||
|
fun cancel() {
|
||||||
|
cancelled = true
|
||||||
|
}
|
||||||
|
|
||||||
fun flashDevice(usbManager: UsbManager, device: UsbDevice, callback: FlashCallback) {
|
fun flashDevice(usbManager: UsbManager, device: UsbDevice, callback: FlashCallback) {
|
||||||
|
cancelled = false
|
||||||
Thread {
|
Thread {
|
||||||
try {
|
try {
|
||||||
doFlash(usbManager, device, callback)
|
doFlash(usbManager, device, callback)
|
||||||
|
|
@ -47,6 +55,7 @@ class EspFlasher(private val context: Context) {
|
||||||
|
|
||||||
private fun doFlash(usbManager: UsbManager, device: UsbDevice, callback: FlashCallback) {
|
private fun doFlash(usbManager: UsbManager, device: UsbDevice, callback: FlashCallback) {
|
||||||
Thread.sleep(500)
|
Thread.sleep(500)
|
||||||
|
if (cancelled) return
|
||||||
|
|
||||||
val connection = usbManager.openDevice(device)
|
val connection = usbManager.openDevice(device)
|
||||||
?: throw IOException("Kan USB-apparaat niet openen")
|
?: throw IOException("Kan USB-apparaat niet openen")
|
||||||
|
|
@ -67,6 +76,7 @@ class EspFlasher(private val context: Context) {
|
||||||
postProgress(callback, 0, "Verbinden met ESP bootloader...")
|
postProgress(callback, 0, "Verbinden met ESP bootloader...")
|
||||||
|
|
||||||
val transport = UsbSerialTransport(connection, epOut, epIn)
|
val transport = UsbSerialTransport(connection, epOut, epIn)
|
||||||
|
if (cancelled) return
|
||||||
|
|
||||||
val assets = context.assets
|
val assets = context.assets
|
||||||
val bootloader = assets.open("firmware/bootloader.bin").readBytes()
|
val bootloader = assets.open("firmware/bootloader.bin").readBytes()
|
||||||
|
|
@ -107,6 +117,7 @@ class EspFlasher(private val context: Context) {
|
||||||
stub.eraseFlash()
|
stub.eraseFlash()
|
||||||
|
|
||||||
for (step in steps) {
|
for (step in steps) {
|
||||||
|
if (cancelled) return
|
||||||
val sizeStr = if (step.data.size > 1024) "${step.data.size / 1024}KB" else "${step.data.size} bytes"
|
val sizeStr = if (step.data.size > 1024) "${step.data.size / 1024}KB" else "${step.data.size} bytes"
|
||||||
postProgress(callback, step.baseProgress, "${step.name} schrijven ($sizeStr)...")
|
postProgress(callback, step.baseProgress, "${step.name} schrijven ($sizeStr)...")
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,7 @@ class SettingsActivity : AppCompatActivity() {
|
||||||
private var currentAction = UsbAction.NONE
|
private var currentAction = UsbAction.NONE
|
||||||
private var progressDialog: AlertDialog? = null
|
private var progressDialog: AlertDialog? = null
|
||||||
private var dialog: AlertDialog? = null
|
private var dialog: AlertDialog? = null
|
||||||
|
private var flasher: EspFlasher? = null
|
||||||
private val handler = Handler(Looper.getMainLooper())
|
private val handler = Handler(Looper.getMainLooper())
|
||||||
|
|
||||||
private val usbAttachedReceiver = object : BroadcastReceiver() {
|
private val usbAttachedReceiver = object : BroadcastReceiver() {
|
||||||
|
|
@ -120,6 +121,8 @@ class SettingsActivity : AppCompatActivity() {
|
||||||
override fun onDestroy() {
|
override fun onDestroy() {
|
||||||
super.onDestroy()
|
super.onDestroy()
|
||||||
currentAction = UsbAction.NONE
|
currentAction = UsbAction.NONE
|
||||||
|
flasher?.cancel()
|
||||||
|
flasher = null
|
||||||
try { unregisterReceiver(usbAttachedReceiver) } catch (e: Exception) {}
|
try { unregisterReceiver(usbAttachedReceiver) } catch (e: Exception) {}
|
||||||
try { unregisterReceiver(usbPermissionReceiver) } catch (e: Exception) {}
|
try { unregisterReceiver(usbPermissionReceiver) } catch (e: Exception) {}
|
||||||
try { unregisterReceiver(usbDetachedReceiver) } catch (e: Exception) {}
|
try { unregisterReceiver(usbDetachedReceiver) } catch (e: Exception) {}
|
||||||
|
|
@ -203,8 +206,8 @@ class SettingsActivity : AppCompatActivity() {
|
||||||
private fun doFlashing(usbManager: UsbManager, device: UsbDevice) {
|
private fun doFlashing(usbManager: UsbManager, device: UsbDevice) {
|
||||||
showProgressDialog("Firmware Flashen", "Initialiseren...", STYLE_HORIZONTAL)
|
showProgressDialog("Firmware Flashen", "Initialiseren...", STYLE_HORIZONTAL)
|
||||||
|
|
||||||
val flasher = EspFlasher(this)
|
flasher = EspFlasher(this)
|
||||||
flasher.flashDevice(usbManager, device, object : EspFlasher.FlashCallback {
|
flasher?.flashDevice(usbManager, device, object : EspFlasher.FlashCallback {
|
||||||
override fun onProgress(percent: Int, message: String) {
|
override fun onProgress(percent: Int, message: String) {
|
||||||
runOnUiThread {
|
runOnUiThread {
|
||||||
val d = progressDialog ?: return@runOnUiThread
|
val d = progressDialog ?: return@runOnUiThread
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue