Retrying DFU

This commit is contained in:
Aleksander Nowakowski 2019-02-20 10:06:22 +01:00
parent 85e7a002e4
commit 00805e1fc2
5 changed files with 46 additions and 4 deletions

View File

@ -707,6 +707,10 @@ import no.nordicsemi.android.dfu.internal.scanner.BootloaderScannerFactory;
if (newAddress != null)
intent.putExtra(DfuBaseService.EXTRA_DEVICE_ADDRESS, newAddress);
// Reset the DFU attempt counter
intent.putExtra(DfuBaseService.EXTRA_DFU_ATTEMPT, 0);
mService.startService(intent);
}

View File

@ -1347,9 +1347,19 @@ public abstract class DfuBaseService extends IntentService implements DfuProgres
mProgressInfo.setProgress(PROGRESS_ABORTED);
} catch (final DeviceDisconnectedException e) {
sendLogBroadcast(LOG_LEVEL_ERROR, "Device has disconnected");
// TODO reconnect n times?
loge(e.getMessage());
close(gatt);
final int attempt = intent.getIntExtra(EXTRA_DFU_ATTEMPT, 0);
final int limit = intent.getIntExtra(EXTRA_MAX_DFU_ATTEMPTS, 0);
if (attempt < limit) {
logi("Restarting the service (" + (attempt + 1) + " /" + limit + ")");
final Intent newIntent = new Intent();
newIntent.fillIn(intent, Intent.FILL_IN_COMPONENT | Intent.FILL_IN_PACKAGE);
newIntent.putExtra(EXTRA_DFU_ATTEMPT, attempt + 1);
startService(newIntent);
return;
}
report(ERROR_DEVICE_DISCONNECTED);
} catch (final DfuException e) {
int error = e.getErrorNumber();

View File

@ -79,6 +79,7 @@ public class DfuServiceInitiator {
private boolean forceDfu = false;
private boolean enableUnsafeExperimentalButtonlessDfu = false;
private boolean disableResume = false;
private int numberOfRetries = 0; // 0 to be backwards compatible
private Boolean packetReceiptNotificationsEnabled;
private int numberOfPackets = 12;
@ -269,6 +270,28 @@ public class DfuServiceInitiator {
return this;
}
/**
* Sets the number of retries that the DFU service will use to complete DFU. The default
* value is 0, for backwards compatibility reason.
* <p>
* If the given value is greater than 0, the service will restart itself at most {@code max}
* times in case of an undesired disconnection during DFU operation. This attempt counter
* is independent from another counter, for reconnection attempts, which is equal to 3.
* The latter one will be used when connection will fail with an error (possible packet
* collision or any other reason). After successful connection, the reconnection counter is
* reset, while the retry counter is cleared after a DFU finishes with success.
* <p>
* The service will not try to retry DFU in case of any other error, for instance an error
* sent from the target device.
*
* @param max Maximum number of retires to complete DFU. Usually around 2.
* @return the builder
*/
public DfuServiceInitiator setNumberOfRetries(@IntRange(from = 0) final int max) {
this.numberOfRetries = max;
return this;
}
/**
* Sets the Maximum Transfer Unit (MTU) value that the Secure DFU service will try to request
* before performing DFU. By default, value 517 will be used, which is the highest supported
@ -704,6 +727,7 @@ public class DfuServiceInitiator {
intent.putExtra(DfuBaseService.EXTRA_RESTORE_BOND, restoreBond);
intent.putExtra(DfuBaseService.EXTRA_FORCE_DFU, forceDfu);
intent.putExtra(DfuBaseService.EXTRA_DISABLE_RESUME, disableResume);
intent.putExtra(DfuBaseService.EXTRA_MAX_DFU_ATTEMPTS, numberOfRetries);
if (mtu > 0)
intent.putExtra(DfuBaseService.EXTRA_MTU, mtu);
intent.putExtra(DfuBaseService.EXTRA_CURRENT_MTU, currentMtu);

View File

@ -474,7 +474,6 @@ import no.nordicsemi.android.error.LegacyDfuError;
} catch (final DeviceDisconnectedException e) {
loge("Disconnected while sending data");
throw e;
// TODO reconnect?
}
final long endTime = SystemClock.elapsedRealtime();

View File

@ -391,8 +391,13 @@ class SecureDfuImpl extends BaseCustomDfuImpl {
mService.sendLogBroadcast(DfuBaseService.LOG_LEVEL_APPLICATION, "Command object created");
}
// Write Init data to the Packet Characteristic
logi("Sending " + (mInitPacketSizeInBytes - info.offset) + " bytes of init packet...");
writeInitData(mPacketCharacteristic, crc32);
try {
logi("Sending " + (mInitPacketSizeInBytes - info.offset) + " bytes of init packet...");
writeInitData(mPacketCharacteristic, crc32);
} catch (final DeviceDisconnectedException e) {
loge("Disconnected while sending init packet");
throw e;
}
final int crc = (int) (crc32.getValue() & 0xFFFFFFFFL);
mService.sendLogBroadcast(DfuBaseService.LOG_LEVEL_APPLICATION, String.format(Locale.US, "Command object sent (CRC = %08X)", crc));