package eu.depau.ddroid.services import android.content.Intent import android.hardware.usb.UsbDevice import android.net.Uri import com.github.mjdev.libaums.UsbMassStorageDevice import eu.depau.ddroid.abc.UsbWriteService import eu.depau.ddroid.utils.getFileSize import eu.depau.ddroid.utils.name import java.nio.ByteBuffer class UsbAPIWriteService : UsbWriteService("UsbAPIWriteService") { class Action { val WRITE_IMAGE = "eu.depau.ddroid.action.API_WRITE_IMAGE" val WRITE_CANCEL = "eu.depau.ddroid.action.API_WRITE_CANCEL" } override fun onHandleIntent(intent: Intent?) { val uri: Uri = intent!!.data!! val usbDevice: UsbDevice = intent.getParcelableExtra("usbDevice") startForeground(FOREGROUND_ID, buildForegroundNotification(usbDevice.name, uri, -1, -1)) try { val notify = { bytes: Long, total: Long -> updateNotification(usbDevice.name, uri, bytes, total) } writeImage(usbDevice, uri, notify) } finally { stopForeground(true) } } private fun getUsbMSDevice(usbDevice: UsbDevice): UsbMassStorageDevice? { val msDevs = UsbMassStorageDevice.getMassStorageDevices(this) for (dev in msDevs) { if (dev.usbDevice == usbDevice) return dev } return null } private fun writeImage(usbDevice: UsbDevice, uri: Uri, notify: (Long, Long) -> Unit): Long { val msDev = getUsbMSDevice(usbDevice)!! msDev.init() val blockDev = msDev.blockDevice val byteBuffer = ByteBuffer.allocate(blockDev.blockSize) val imageSize = uri.getFileSize(this) val inputStream = contentResolver.openInputStream(uri)!! var readBytes: Int var offset = 0L while (true) { readBytes = inputStream.read(byteBuffer.array()!!) if (readBytes < 0) break byteBuffer.position(readBytes) blockDev.write(offset, byteBuffer) offset++ notify(offset * blockDev.blockSize, imageSize) } msDev.close() return offset * blockDev.blockSize } }