Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,12 @@ class PrepareDataObjectDelaySettingsEvent(private val delay: Int) : DFUSettingsC
override fun createBundle() = bundleOf(FirebaseParam.VALUE to delay)
}

class ExecuteInitDelaySettingsEvent(private val delay: Int) : DFUSettingsChangeEvent {
override val eventName: String = "EXECUTE_INIT_DELAY_EVENT"

override fun createBundle() = bundleOf(FirebaseParam.VALUE to delay)
}

class RebootTimeSettingsEvent(private val rebootTime: Int) : DFUSettingsChangeEvent {
override val eventName: String = "REBOOT_TIME_EVENT"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,11 @@ public abstract class DfuBaseService extends IntentService implements DfuProgres
* in milliseconds. This defaults to 0 for backwards compatibility reason.
*/
public static final String EXTRA_DATA_OBJECT_DELAY = "no.nordicsemi.android.dfu.extra.EXTRA_DATA_OBJECT_DELAY";
/**
* The duration of a delay that will be added after sending the Init Packet and before
* executing it, in milliseconds. This defaults to 0 for backwards compatibility reason.
*/
public static final String EXTRA_INIT_EXECUTE_DELAY = "no.nordicsemi.android.dfu.extra.EXTRA_INIT_EXECUTE_DELAY";
/**
* This property must contain a boolean value.
* <p>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ public final class DfuServiceInitiator {
private int numberOfRetries = 0; // 0 to be backwards compatible
private int mbrSize = DEFAULT_MBR_SIZE;
private long dataObjectDelay = 0; // initially disabled
private long executeInitDelay = 0; // initially disabled
private long rebootTime = 0; // ms
private long scanTimeout = DEFAULT_SCAN_TIMEOUT; // ms

Expand Down Expand Up @@ -245,6 +246,19 @@ public DfuServiceInitiator setPrepareDataObjectDelay(final long delay) {
return this;
}

/**
* This method sets the duration of a delay, that the service will wait after sending the
* init packet and before executing it. The delay will be done after the init packet is sent
* and before sending the execute command. The default value is 0, which disables this feature.
*
* @param delay the delay that the service will wait before executing the init packet in milliseconds.
* @return the builder
*/
public DfuServiceInitiator setExecuteInitDelay(final long delay) {
this.executeInitDelay = delay;
return this;
}

/**
* Enables or disables the Packet Receipt Notification (PRN) procedure.
* <p>
Expand Down Expand Up @@ -870,6 +884,7 @@ public DfuServiceController start(@NonNull final Context context, @NonNull final
intent.putExtra(DfuBaseService.EXTRA_MAX_DFU_ATTEMPTS, numberOfRetries);
intent.putExtra(DfuBaseService.EXTRA_MBR_SIZE, mbrSize);
intent.putExtra(DfuBaseService.EXTRA_DATA_OBJECT_DELAY, dataObjectDelay);
intent.putExtra(DfuBaseService.EXTRA_INIT_EXECUTE_DELAY, executeInitDelay);
intent.putExtra(DfuBaseService.EXTRA_SCAN_TIMEOUT, scanTimeout);
intent.putExtra(DfuBaseService.EXTRA_SCAN_DELAY, rebootTime);
if (mtu > 0)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ class SecureDfuImpl extends BaseCustomDfuImpl {
private BluetoothGattCharacteristic mPacketCharacteristic;

private long prepareObjectDelay;
private long executeInitDelay;

private final SecureBluetoothCallback mBluetoothCallback = new SecureBluetoothCallback();

Expand Down Expand Up @@ -223,6 +224,7 @@ public void performDfu(@NonNull final Intent intent)
}

prepareObjectDelay = intent.getLongExtra(DfuBaseService.EXTRA_DATA_OBJECT_DELAY, 0);
executeInitDelay = intent.getLongExtra(DfuBaseService.EXTRA_INIT_EXECUTE_DELAY, 0);

try {
// Enable notifications
Expand Down Expand Up @@ -472,6 +474,8 @@ private void sendInitPacket(@NonNull final BluetoothGatt gatt, final boolean all
}

// Execute Init packet. It's better to execute it twice than not execute at all...
if (executeInitDelay > 0)
mService.waitFor(executeInitDelay);
logi("Executing init packet (Op Code = 4)");
writeExecute();
mService.sendLogBroadcast(DfuBaseService.LOG_LEVEL_APPLICATION, "Command object executed");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ data class DFUSettings(
val externalMcuDfu: Boolean = false,
val disableResume: Boolean = false,
val prepareDataObjectDelay: Int = 0, // ms
val executeInitDelay: Int = 0, // ms
val rebootTime: Int = 0, // ms
val scanTimeout: Int = 6_000, // ms
val mtuRequestEnabled: Boolean = true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ private val DISABLE_RESUME = booleanPreferencesKey("disable_resume")
private val FORCE_SCANNING_ADDRESS = booleanPreferencesKey("force_scanning_address")
private val NUMBER_OF_POCKETS_KEY = intPreferencesKey("number_of_pockets")
private val PREPARE_OBJECT_DELAY_KEY = intPreferencesKey("prepare_data_object_delay")
private val EXECUTE_INIT_DELAY_KEY = intPreferencesKey("execute_init_delay")
private val REBOOT_TIME_KEY = intPreferencesKey("reboot_time")
private val SCAN_TIMEOUT_KEY = intPreferencesKey("scan_timeout")
private val MTU = booleanPreferencesKey("requestMtu")
Expand All @@ -75,6 +76,7 @@ class SettingsDataSource @Inject constructor(
context.dataStore.edit {
it[PACKETS_RECEIPT_NOTIFICATION_KEY] = settings.packetsReceiptNotification
it[PREPARE_OBJECT_DELAY_KEY] = settings.prepareDataObjectDelay
it[EXECUTE_INIT_DELAY_KEY] = settings.executeInitDelay
it[REBOOT_TIME_KEY] = settings.rebootTime
it[SCAN_TIMEOUT_KEY] = settings.scanTimeout
it[NUMBER_OF_POCKETS_KEY] = settings.numberOfPackets
Expand All @@ -95,6 +97,7 @@ class SettingsDataSource @Inject constructor(
this[EXTERNAL_MCU_KEY] ?: false,
this[DISABLE_RESUME] ?: false,
this[PREPARE_OBJECT_DELAY_KEY] ?: 400,
this[EXECUTE_INIT_DELAY_KEY] ?: 0,
this[REBOOT_TIME_KEY] ?: 0,
this[SCAN_TIMEOUT_KEY] ?: 2_000,
this[MTU] ?: true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ internal class DFUManager @Inject constructor(

setForceScanningForNewAddressInLegacyDfu(settings.forceScanningInLegacyDfu)
setPrepareDataObjectDelay(settings.prepareDataObjectDelay.toLong())
setExecuteInitDelay(settings.executeInitDelay.toLong())
setRebootTime(settings.rebootTime.toLong())
setScanTimeout(settings.scanTimeout.toLong())
setUnsafeExperimentalButtonlessServiceInSecureDfuEnabled(true)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,15 @@ internal fun SettingsScreen(
onChange = { onEvent(OnPrepareDataObjectDelayChange(it)) }
)

SettingsTimeSlider(
text = stringResource(id = R.string.dfu_settings_execute_init_delay),
description = stringResource(id = R.string.dfu_settings_execute_init_delay_info),
value = state.executeInitDelay,
valueRange = 0..1000,
stepInMilliseconds = 100, // 0.1 seconds
onChange = { onEvent(OnExecuteInitDelayChange(it)) }
)

Headline(stringResource(id = R.string.dfu_settings_headline_legacy_dfu))

SettingsSwitch(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ internal data class OnNumberOfPocketsChange(val numberOfPockets: Int) : Settings

internal data class OnPrepareDataObjectDelayChange(val delay: Int) : SettingsScreenViewEvent

internal data class OnExecuteInitDelayChange(val delay: Int) : SettingsScreenViewEvent

internal data class OnRebootTimeChange(val time: Int) : SettingsScreenViewEvent

internal data class OnScanTimeoutChange(val timeout: Int) : SettingsScreenViewEvent
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ internal class SettingsViewModel @Inject constructor(
OnForceScanningAddressesSwitchClick -> onForceScanningAddressesSwitchClick()
is OnNumberOfPocketsChange -> onNumberOfPocketsChange(event.numberOfPockets)
is OnPrepareDataObjectDelayChange -> onPrepareDataObjectDelayChange(event.delay)
is OnExecuteInitDelayChange -> onExecuteInitDelayChange(event.delay)
is OnRebootTimeChange -> onRebootTimeChange(event.time)
is OnScanTimeoutChange -> onScanTimeoutChange(event.timeout)
}
Expand Down Expand Up @@ -144,6 +145,14 @@ internal class SettingsViewModel @Inject constructor(
analytics.logEvent(PrepareDataObjectDelaySettingsEvent(newSettings.prepareDataObjectDelay))
}

private fun onExecuteInitDelayChange(delay: Int) {
val newSettings = state.value.copy(executeInitDelay = delay)
viewModelScope.launch {
repository.storeSettings(newSettings)
}
analytics.logEvent(ExecuteInitDelaySettingsEvent(newSettings.executeInitDelay))
}

private fun onRebootTimeChange(rebootTime: Int) {
val newSettings = state.value.copy(rebootTime = rebootTime)
viewModelScope.launch {
Expand Down
2 changes: 2 additions & 0 deletions profile/settings/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@
<string name="dfu_settings_disable_resume_info">When the resume feature is disabled the app will not try to resume previously interrupted update.</string>
<string name="dfu_settings_prepare_data_object_delay">Prepare object delay</string>
<string name="dfu_settings_prepare_data_object_delay_info">The time required by the DFU bootloader to save the data object in flash memory. Shorter delays will increase upload speed, but may cause issues on some devices.</string>
<string name="dfu_settings_execute_init_delay">Execute init delay</string>
<string name="dfu_settings_execute_init_delay_info">The time the service will wait after sending the init packet and before executing it.</string>
<string name="dfu_settings_reboot_time">Reboot time</string>
<string name="dfu_settings_reboot_time_info">The time the device needs to reboot into the DFU bootloader mode. The app will delay scanning for the bootloader.</string>
<string name="dfu_settings_scan_timeout">Scan timeout</string>
Expand Down