diff --git a/dfu/src/main/java/no/nordicsemi/android/dfu/BaseCustomDfuImpl.java b/dfu/src/main/java/no/nordicsemi/android/dfu/BaseCustomDfuImpl.java index 9c57036..6f999b7 100644 --- a/dfu/src/main/java/no/nordicsemi/android/dfu/BaseCustomDfuImpl.java +++ b/dfu/src/main/java/no/nordicsemi/android/dfu/BaseCustomDfuImpl.java @@ -425,7 +425,7 @@ import no.nordicsemi.android.dfu.internal.scanner.BootloaderScannerFactory; boolean alreadyWaited = false; if (mGatt.getDevice().getBondState() == BluetoothDevice.BOND_BONDED) { final boolean restoreBond = intent.getBooleanExtra(DfuBaseService.EXTRA_RESTORE_BOND, false); - if (restoreBond || !keepBond || (mFileType & DfuBaseService.TYPE_SOFT_DEVICE) > 0) { + if (restoreBond || !keepBond) { // The bond information was lost. removeBond(); diff --git a/dfu/src/main/java/no/nordicsemi/android/dfu/BaseDfuImpl.java b/dfu/src/main/java/no/nordicsemi/android/dfu/BaseDfuImpl.java index 9e111c8..a5abeba 100644 --- a/dfu/src/main/java/no/nordicsemi/android/dfu/BaseDfuImpl.java +++ b/dfu/src/main/java/no/nordicsemi/android/dfu/BaseDfuImpl.java @@ -272,7 +272,16 @@ import no.nordicsemi.android.dfu.internal.exception.UploadAbortedException; // not work by default on iOS with buttonless update on SDKs < 8 on bonded devices. The bootloader must be modified to // always send the indication when connected. - // This has been fixed on Android 6. Now the Android enables Service Changed indications automatically after bonding. + // The requirement of enabling Service Changed indications manually has been fixed on Android 6. + // Now the Android enables Service Changed indications automatically after bonding. + // + // However, be aware, that in SDK 8 (and perhaps some never) the Service Changed CCCD state is saved on DISCONNECT event on the nRF. + // That means, that if a user has connected to a new device, bonded and enabled SC indications (manually on automatically) the + // setting will not be preserved in flash if DFU is started immediately. Jumping to DFU mode causes reset, not a DISCONNECT, so the + // CCCD value will be lost and SC indication will not be sent from the bootloader. + // If the device has disconnected at least once after SC CCCD value was written everything will work. + // Also, the Secure DFU does not support sharing bond information between App and Bootloader (instead it uses address+1 trick, so no bonding), + // so this issue does no apply there. if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M && gatt.getDevice().getBondState() == BluetoothDevice.BOND_BONDED) { final BluetoothGattService genericAttributeService = gatt.getService(GENERIC_ATTRIBUTE_SERVICE_UUID); if (genericAttributeService != null) { @@ -288,28 +297,28 @@ import no.nordicsemi.android.dfu.internal.exception.UploadAbortedException; /* * NOTE: The DFU Bootloader from SDK 8.0 (v0.6 and 0.5) has the following issue: * - * When the central device (phone) connects to a bonded device (or connects and bonds) which supports the Service Changed characteristic, + * When a central device (phone) connects to a bonded device (or connects and bonds) which supports the Service Changed characteristic, * but does not have the Service Changed indications enabled, the phone must enable them, disconnect and reconnect before starting the * DFU operation. This is because the current version of the Soft Device saves the ATT table on the DISCONNECTED event. - * Sending the "jump to Bootloader" command (0x01-04) will cause the disconnect followed be a reset. The Soft Device does not + * Sending the "jump to Bootloader" command (0x01-04) will cause the disconnect followed be a reset. The SoftDevice does not * have time to store the ATT table on Flash memory before the reset. * * This applies only if: * - the device was bonded before an upgrade, - * - the Application or the Bootloader is upgraded (upgrade of the Soft Device will erase the bond information anyway), - * - Application: + * - In case of an Application update: + * - For Legacy DFU: * if the DFU Bootloader has been modified and compiled to preserve the LTK and the ATT table after application upgrade (at least 2 pages) - * See: \Nordic\nrf51\components\libraries\bootloader_dfu\dfu_types.h, line 56(?): - * #define DFU_APP_DATA_RESERVED 0x0000 -> 0x0800+ //< Size of Application Data that must be preserved between application updates... - * - Bootloader: - * The Application memory should not be removed when the Bootloader is upgraded, so the Bootloader configuration does not matter. + * See: http://infocenter.nordicsemi.com/topic/com.nordic.infocenter.sdk5.v11.0.0/bledfu_memory_banks.html?cp=4_0_3_4_3_1_3_2 -> Preserving application data + * - For Secure DFU: + * the default number of pages to be preserved is set to 3. That includes the LTK and ATT table + * See: http://infocenter.nordicsemi.com/topic/com.nordic.infocenter.sdk5.v12.0.0/lib_bootloader_dfu_banks.html#lib_bootloader_dfu_appdata -> Preserving application data * * If the bond information is not to be preserved between the old and new applications, we may skip this disconnect/reconnect process. * The DFU Bootloader will send the SD indication anyway when we will just continue here, as the information whether it should send it or not it is not being * read from the application's ATT table, but rather passed as an argument of the "reboot to bootloader" method. */ final boolean keepBond = intent.getBooleanExtra(DfuBaseService.EXTRA_KEEP_BOND, false); - if (keepBond && (mFileType & DfuBaseService.TYPE_SOFT_DEVICE) == 0) { + if (keepBond) { mService.sendLogBroadcast(DfuBaseService.LOG_LEVEL_VERBOSE, "Restarting service..."); // Disconnect diff --git a/dfu/src/main/java/no/nordicsemi/android/dfu/DfuBaseService.java b/dfu/src/main/java/no/nordicsemi/android/dfu/DfuBaseService.java index 8981ba5..0cd6879 100644 --- a/dfu/src/main/java/no/nordicsemi/android/dfu/DfuBaseService.java +++ b/dfu/src/main/java/no/nordicsemi/android/dfu/DfuBaseService.java @@ -129,9 +129,9 @@ public abstract class DfuBaseService extends IntentService implements DfuProgres * If an application is being updated on a bonded device with the DFU Bootloader that has been configured to preserve the bond information for the new application, * set it to true.

* - *

By default the DFU Bootloader clears the whole application's memory. It may be however configured in the \Nordic\nrf51\components\libraries\bootloader_dfu\dfu_types.h + *

By default the Legacy DFU Bootloader clears the whole application's memory. It may be however configured in the \Nordic\nrf51\components\libraries\bootloader_dfu\dfu_types.h * file (sdk 11, line 76: #define DFU_APP_DATA_RESERVED 0x0000) to preserve some pages. The BLE_APP_HRM_DFU sample app stores the LTK and System Attributes in the first - * two pages, so in order to preserve the bond information this value should be changed to 0x0800 or more. + * two pages, so in order to preserve the bond information this value should be changed to 0x0800 or more. For Secure DFU this value is by default set to 3 pages. * When those data are preserved, the new Application will notify the app with the Service Changed indication when launched for the first time. Otherwise this * service will remove the bond information from the phone and force to refresh the device cache (see {@link #refreshDeviceCache(android.bluetooth.BluetoothGatt, boolean)}).

* diff --git a/dfu/src/main/java/no/nordicsemi/android/dfu/ExperimentalButtonlessDfuImpl.java b/dfu/src/main/java/no/nordicsemi/android/dfu/ExperimentalButtonlessDfuImpl.java index 68088ba..2ecbca9 100644 --- a/dfu/src/main/java/no/nordicsemi/android/dfu/ExperimentalButtonlessDfuImpl.java +++ b/dfu/src/main/java/no/nordicsemi/android/dfu/ExperimentalButtonlessDfuImpl.java @@ -142,7 +142,7 @@ public class ExperimentalButtonlessDfuImpl extends BaseDfuImpl { mService.sendLogBroadcast(DfuBaseService.LOG_LEVEL_INFO, "Disconnected by the remote device"); - finalize(intent, true); + finalize(intent, false); // Secure DFU by default preserves 3 pages of App Data, those include Att table and bond information } catch (final UnknownResponseException e) { final int error = DfuBaseService.ERROR_INVALID_RESPONSE; loge(e.getMessage()); @@ -157,7 +157,8 @@ public class ExperimentalButtonlessDfuImpl extends BaseDfuImpl { } /** - * Closes the BLE connection to the device and removes bonding, if a proper flags were set in the {@link DfuServiceInitiator}. + * Closes the BLE connection to the device and removes bonding information if a proper flag was NOT set + * in the {@link DfuServiceInitiator#setKeepBond(boolean)}. * This method will scan for a bootloader advertising with the address equal to the current or incremented by 1 and restart the service. * @param intent the intent used to start the DFU service. It contains all user flags in the bundle. * @param forceRefresh true, if cache should be cleared even for a bonded device. Usually the Service Changed indication should be used for this purpose. @@ -181,7 +182,7 @@ public class ExperimentalButtonlessDfuImpl extends BaseDfuImpl { */ if (mGatt.getDevice().getBondState() == BluetoothDevice.BOND_BONDED) { final boolean restoreBond = intent.getBooleanExtra(DfuBaseService.EXTRA_RESTORE_BOND, false); - if (restoreBond || !keepBond || (mFileType & DfuBaseService.TYPE_SOFT_DEVICE) > 0) { + if (restoreBond || !keepBond) { // The bond information was lost. removeBond(); diff --git a/dfu/src/main/java/no/nordicsemi/android/dfu/LegacyDfuImpl.java b/dfu/src/main/java/no/nordicsemi/android/dfu/LegacyDfuImpl.java index 155d31f..f7eec91 100644 --- a/dfu/src/main/java/no/nordicsemi/android/dfu/LegacyDfuImpl.java +++ b/dfu/src/main/java/no/nordicsemi/android/dfu/LegacyDfuImpl.java @@ -288,7 +288,7 @@ import no.nordicsemi.android.error.LegacyDfuError; * [Vol. 3, Part G, 2.5.2 - Attribute Caching] * Note: Clients without a trusted relationship must perform service discovery on each connection if the server supports the Services Changed characteristic. * - * However, as up to Android 5 the system does NOT respect this requirement and servers are cached for every device, even if Service Changed is enabled -> Android BUG? + * However, as up to Android 7 the system does NOT respect this requirement and servers are cached for every device, even if Service Changed is enabled -> Android BUG? * For bonded devices Android performs service re-discovery when SC indication is received. */ final BluetoothGattService gas = gatt.getService(GENERIC_ATTRIBUTE_SERVICE_UUID);