From edaf9446a1ceaf30923474dd059ba6ce5d767f47 Mon Sep 17 00:00:00 2001 From: Harold Cooper Date: Mon, 31 Aug 2015 16:12:13 -0400 Subject: [PATCH 1/6] ability to disable the progress notification in the status bar --- .../android/dfu/DfuBaseService.java | 22 ++++++++++++++----- .../android/dfu/DfuServiceInitiator.java | 14 ++++++++++++ 2 files changed, 31 insertions(+), 5 deletions(-) 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 6cd2b63..03406e1 100644 --- a/dfu/src/main/java/no/nordicsemi/android/dfu/DfuBaseService.java +++ b/dfu/src/main/java/no/nordicsemi/android/dfu/DfuBaseService.java @@ -106,6 +106,10 @@ public abstract class DfuBaseService extends IntentService { * The optional device name. This name will be shown in the notification. */ public static final String EXTRA_DEVICE_NAME = "no.nordicsemi.android.dfu.extra.EXTRA_DEVICE_NAME"; + /** + * A boolean indicating whether to disable the progress notification in the status bar. Defaults to false. + */ + public static final String EXTRA_DISABLE_NOTIFICATION = "no.nordicsemi.android.dfu.extra.EXTRA_DISABLE_NOTIFICATION"; /** *

* If the new firmware (application) does not share the bond information with the old one, the bond information is lost. Set this flag to true @@ -543,6 +547,7 @@ public abstract class DfuBaseService extends IntentService { private InputStream mInputStream; private String mDeviceAddress; private String mDeviceName; + private boolean mDisableNotification; /** * The current connection state. If its value is > 0 than an error has occurred. Error number is a negative value of mConnectionState */ @@ -1075,6 +1080,7 @@ public abstract class DfuBaseService extends IntentService { // Read input parameters final String deviceAddress = intent.getStringExtra(EXTRA_DEVICE_ADDRESS); final String deviceName = intent.getStringExtra(EXTRA_DEVICE_NAME); + final boolean disableNotification = intent.getBooleanExtra(EXTRA_DISABLE_NOTIFICATION, false); final String filePath = intent.getStringExtra(EXTRA_FILE_PATH); final Uri fileUri = intent.getParcelableExtra(EXTRA_FILE_URI); final int fileResId = intent.getIntExtra(EXTRA_FILE_RES_ID, 0); @@ -1105,6 +1111,7 @@ public abstract class DfuBaseService extends IntentService { mDeviceAddress = deviceAddress; mDeviceName = deviceName; + mDisableNotification = disableNotification; mConnectionState = STATE_DISCONNECTED; mBytesSent = 0; mBytesConfirmed = 0; @@ -2675,6 +2682,16 @@ public abstract class DfuBaseService extends IntentService { * {@link #PROGRESS_VALIDATING}, {@link #PROGRESS_DISCONNECTING}, {@link #PROGRESS_COMPLETED} or {@link #ERROR_FILE_ERROR}, {@link #ERROR_FILE_INVALID} , etc */ private void updateProgressNotification(final int progress) { + + // send progress or error broadcast + if (progress < ERROR_MASK) + sendProgressBroadcast(progress); + else + sendErrorBroadcast(progress); + + if (mDisableNotification) return; + // create or update notification: + final String deviceAddress = mDeviceAddress; final String deviceName = mDeviceName != null ? mDeviceName : getString(R.string.dfu_unknown_name); @@ -2722,11 +2739,6 @@ public abstract class DfuBaseService extends IntentService { builder.setOngoing(true).setContentTitle(title).setContentText(text).setProgress(100, progress, false); } } - // send progress or error broadcast - if (progress < ERROR_MASK) - sendProgressBroadcast(progress); - else - sendErrorBroadcast(progress); // update the notification final Intent intent = new Intent(this, getNotificationTarget()); diff --git a/dfu/src/main/java/no/nordicsemi/android/dfu/DfuServiceInitiator.java b/dfu/src/main/java/no/nordicsemi/android/dfu/DfuServiceInitiator.java index 551265e..44fbd50 100644 --- a/dfu/src/main/java/no/nordicsemi/android/dfu/DfuServiceInitiator.java +++ b/dfu/src/main/java/no/nordicsemi/android/dfu/DfuServiceInitiator.java @@ -38,6 +38,8 @@ public class DfuServiceInitiator { private final String deviceAddress; private String deviceName; + private boolean disableNotification; + private Uri fileUri; private String filePath; private int fileResId; @@ -71,6 +73,17 @@ public class DfuServiceInitiator { return this; } + /** + * Sets whether the progress notification in the status bar should be disabled. + * Defaults to false. + * @param disableNotification whether to disable the notification + * @return the builder + */ + public DfuServiceInitiator setDisableNotification(final boolean disableNotification) { + this.disableNotification = disableNotification; + return this; + } + /** * Sets whether the bond information should be preserver after flashing new application. This feature requires DFU Bootloader version 0.6 or newer (SDK 8.0.0+). * Please see the {@link DfuBaseService#EXTRA_KEEP_BOND} for more information regarding requirements. Remember that currently updating the Soft Device will remove the bond information. @@ -245,6 +258,7 @@ public class DfuServiceInitiator { intent.putExtra(DfuBaseService.EXTRA_DEVICE_ADDRESS, deviceAddress); intent.putExtra(DfuBaseService.EXTRA_DEVICE_NAME, deviceName); + intent.putExtra(DfuBaseService.EXTRA_DISABLE_NOTIFICATION, disableNotification); intent.putExtra(DfuBaseService.EXTRA_FILE_MIME_TYPE, mimeType); intent.putExtra(DfuBaseService.EXTRA_FILE_TYPE, fileType); intent.putExtra(DfuBaseService.EXTRA_FILE_URI, fileUri); From eec1bbd330d9df0d490d4c6b8ab2b7c78421b6a9 Mon Sep 17 00:00:00 2001 From: Aleksander Nowakowski Date: Mon, 27 Jul 2015 11:11:26 +0200 Subject: [PATCH 2/6] Validating firmware word-alignment --- .idea/encodings.xml | 7 ++-- .../android/dfu/DfuBaseService.java | 34 ++++++++++++++--- .../exception/SizeValidationException.java | 37 +++++++++++++++++++ .../nordicsemi/android/error/GattError.java | 2 + 4 files changed, 71 insertions(+), 9 deletions(-) create mode 100644 dfu/src/main/java/no/nordicsemi/android/dfu/internal/exception/SizeValidationException.java diff --git a/.idea/encodings.xml b/.idea/encodings.xml index e206d70..c2bae49 100644 --- a/.idea/encodings.xml +++ b/.idea/encodings.xml @@ -1,5 +1,6 @@ - - - + + + + \ No newline at end of file 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 03406e1..9e7b436 100644 --- a/dfu/src/main/java/no/nordicsemi/android/dfu/DfuBaseService.java +++ b/dfu/src/main/java/no/nordicsemi/android/dfu/DfuBaseService.java @@ -66,6 +66,7 @@ import no.nordicsemi.android.dfu.internal.exception.DeviceDisconnectedException; import no.nordicsemi.android.dfu.internal.exception.DfuException; import no.nordicsemi.android.dfu.internal.exception.HexFileValidationException; import no.nordicsemi.android.dfu.internal.exception.RemoteDfuException; +import no.nordicsemi.android.dfu.internal.exception.SizeValidationException; import no.nordicsemi.android.dfu.internal.exception.UnknownResponseException; import no.nordicsemi.android.dfu.internal.exception.UploadAbortedException; import no.nordicsemi.android.dfu.internal.scanner.BootloaderScannerFactory; @@ -382,7 +383,7 @@ public abstract class DfuBaseService extends IntentService { */ public static final int ERROR_FILE_ERROR = ERROR_MASK | 0x02; /** - * Thrown then input file is not a valid HEX or ZIP file. + * Thrown when input file is not a valid HEX or ZIP file. */ public static final int ERROR_FILE_INVALID = ERROR_MASK | 0x03; /** @@ -390,7 +391,7 @@ public abstract class DfuBaseService extends IntentService { */ public static final int ERROR_FILE_IO_EXCEPTION = ERROR_MASK | 0x04; /** - * Error thrown then {@code gatt.discoverServices();} returns false. + * Error thrown when {@code gatt.discoverServices();} returns false. */ public static final int ERROR_SERVICE_DISCOVERY_NOT_STARTED = ERROR_MASK | 0x05; /** @@ -417,6 +418,10 @@ public abstract class DfuBaseService extends IntentService { * DFU Bootloader version 0.6+ requires sending the Init packet. If such bootloader version is detected, but the init packet has not been set this error is thrown. */ public static final int ERROR_INIT_PACKET_REQUIRED = ERROR_MASK | 0x0B; + /** + * Thrown when the firmware file is not word-aligned. The firmware size must be dividable by 4 bytes. + */ + public static final int ERROR_FILE_SIZE_INVALID = ERROR_MASK | 0x0C; /** * Flag set then the DFU target returned a DFU error. Look for DFU specification to get error codes. */ @@ -775,6 +780,8 @@ public abstract class DfuBaseService extends IntentService { } } else { loge("Connection state change error: " + status + " newState: " + newState); + if (newState == BluetoothGatt.STATE_DISCONNECTED) + mConnectionState = STATE_DISCONNECTED; mPaused = false; mError = ERROR_CONNECTION_STATE_MASK | status; } @@ -1185,6 +1192,10 @@ public abstract class DfuBaseService extends IntentService { mInputStream = is; imageSizeInBytes = mImageSizeInBytes = is.available(); + + if ((imageSizeInBytes % 4) != 0) + throw new SizeValidationException("The new firmware is not word-aligned."); + // Update the file type bit field basing on the ZIP content if (fileType == TYPE_AUTO && MIME_TYPE_ZIP.equals(mimeType)) { final ArchiveInputStream zhis = (ArchiveInputStream) is; @@ -1194,6 +1205,15 @@ public abstract class DfuBaseService extends IntentService { // Set the Init packet stream in case of a ZIP file if (MIME_TYPE_ZIP.equals(mimeType)) { final ArchiveInputStream zhis = (ArchiveInputStream) is; + + // Validate sizes + if ((fileType & TYPE_APPLICATION) > 0 && (zhis.applicationImageSize() % 4) != 0) + throw new SizeValidationException("Application firmware is not word-aligned."); + if ((fileType & TYPE_BOOTLOADER) > 0 && (zhis.bootloaderImageSize() % 4) != 0) + throw new SizeValidationException("Bootloader firmware is not word-aligned."); + if ((fileType & TYPE_SOFT_DEVICE) > 0 && (zhis.softDeviceImageSize() % 4) != 0) + throw new SizeValidationException("Soft Device firmware is not word-aligned."); + if (fileType == TYPE_APPLICATION) { if (zhis.getApplicationInit() != null) initIs = new ByteArrayInputStream(zhis.getApplicationInit()); @@ -1211,6 +1231,10 @@ public abstract class DfuBaseService extends IntentService { loge("An exception occurred while opening file", e); updateProgressNotification(ERROR_FILE_NOT_FOUND); return; + } catch (final SizeValidationException e) { + loge("Firmware not word-aligned", e); + updateProgressNotification(ERROR_FILE_SIZE_INVALID); + return; } catch (final IOException e) { loge("An exception occurred while calculating file size", e); updateProgressNotification(ERROR_FILE_ERROR); @@ -2856,13 +2880,11 @@ public abstract class DfuBaseService extends IntentService { } private void loge(final String message) { - if (BuildConfig.DEBUG) - Log.e(TAG, message); + Log.e(TAG, message); } private void loge(final String message, final Throwable e) { - if (BuildConfig.DEBUG) - Log.e(TAG, message, e); + Log.e(TAG, message, e); } private void logw(final String message) { diff --git a/dfu/src/main/java/no/nordicsemi/android/dfu/internal/exception/SizeValidationException.java b/dfu/src/main/java/no/nordicsemi/android/dfu/internal/exception/SizeValidationException.java new file mode 100644 index 0000000..037e91f --- /dev/null +++ b/dfu/src/main/java/no/nordicsemi/android/dfu/internal/exception/SizeValidationException.java @@ -0,0 +1,37 @@ +/************************************************************************************************************************************************* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ************************************************************************************************************************************************/ + +package no.nordicsemi.android.dfu.internal.exception; + +import java.io.IOException; + +/** + * This exception is thrown when the firmware size is not word-aligned (number of bytes does not divide by 4). + * This is the requirement for the DFU Bootloader. + */ +public class SizeValidationException extends IOException { + private static final long serialVersionUID = -6467104024030837875L; + + public SizeValidationException(final String message) { + super(message); + } +} diff --git a/dfu/src/main/java/no/nordicsemi/android/error/GattError.java b/dfu/src/main/java/no/nordicsemi/android/error/GattError.java index 5c7ed5a..defb40d 100644 --- a/dfu/src/main/java/no/nordicsemi/android/error/GattError.java +++ b/dfu/src/main/java/no/nordicsemi/android/error/GattError.java @@ -151,6 +151,8 @@ public class GattError { return "DFU FILE ERROR"; case DfuBaseService.ERROR_FILE_INVALID: return "DFU NOT A VALID HEX FILE"; + case DfuBaseService.ERROR_FILE_SIZE_INVALID: + return "DFU FILE NOT WORD ALIGNED"; case DfuBaseService.ERROR_FILE_IO_EXCEPTION: return "DFU IO EXCEPTION"; case DfuBaseService.ERROR_FILE_NOT_FOUND: From 16ef9b899c506850d06dca4a6856c6e72528857e Mon Sep 17 00:00:00 2001 From: Aleksander Nowakowski Date: Fri, 31 Jul 2015 16:57:30 +0200 Subject: [PATCH 3/6] Migration to Android Studio 1.3. --- .idea/runConfigurations.xml | 12 ++++++++++++ DFULibrary.iml | 2 +- dfu/dfu.iml | 8 +++++--- 3 files changed, 18 insertions(+), 4 deletions(-) create mode 100644 .idea/runConfigurations.xml diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml new file mode 100644 index 0000000..7f68460 --- /dev/null +++ b/.idea/runConfigurations.xml @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/DFULibrary.iml b/DFULibrary.iml index 2adf3a9..0778726 100644 --- a/DFULibrary.iml +++ b/DFULibrary.iml @@ -8,7 +8,7 @@ - + diff --git a/dfu/dfu.iml b/dfu/dfu.iml index dfa5a2b..0f43ee0 100644 --- a/dfu/dfu.iml +++ b/dfu/dfu.iml @@ -12,10 +12,12 @@ - + From 5fc5cae70ce6f43a99dd71a333f334c6a90427fa Mon Sep 17 00:00:00 2001 From: Aleksander Nowakowski Date: Wed, 19 Aug 2015 16:02:10 +0200 Subject: [PATCH 4/6] Migration to API 23 and support.v4 version 23.0.0. --- dfu/build.gradle | 8 ++++---- dfu/dfu.iml | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/dfu/build.gradle b/dfu/build.gradle index 33d3d28..517dcf0 100644 --- a/dfu/build.gradle +++ b/dfu/build.gradle @@ -7,12 +7,12 @@ apply plugin: 'com.android.library' //} android { - compileSdkVersion 22 - buildToolsVersion '22.0.1' + compileSdkVersion 23 + buildToolsVersion '23.0.0' defaultConfig { minSdkVersion 18 - targetSdkVersion 22 + targetSdkVersion 23 versionCode 2 versionName "0.6" } @@ -26,7 +26,7 @@ android { dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) - compile 'com.android.support:support-v4:22.2.1' + compile 'com.android.support:support-v4:23.0.0' compile 'com.google.code.gson:gson:2.3.1' } diff --git a/dfu/dfu.iml b/dfu/dfu.iml index 0f43ee0..2e0d735 100644 --- a/dfu/dfu.iml +++ b/dfu/dfu.iml @@ -72,7 +72,7 @@ - + @@ -88,10 +88,10 @@ - + - - + + \ No newline at end of file From 6e4c6a2cddbe5fc0978ef56c3ed606be30640a95 Mon Sep 17 00:00:00 2001 From: Aleksander Nowakowski Date: Tue, 25 Aug 2015 12:57:20 +0200 Subject: [PATCH 5/6] Removing unused tags from AndroidManifest.xml. --- dfu/src/main/AndroidManifest.xml | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/dfu/src/main/AndroidManifest.xml b/dfu/src/main/AndroidManifest.xml index 821c240..c7adc81 100644 --- a/dfu/src/main/AndroidManifest.xml +++ b/dfu/src/main/AndroidManifest.xml @@ -1,11 +1,3 @@ - - - - + From 1126ca5cfa4b0e8353986310349a0bea262b1b96 Mon Sep 17 00:00:00 2001 From: Aleksander Nowakowski Date: Tue, 15 Sep 2015 09:23:28 +0200 Subject: [PATCH 6/6] Migration to support.v4 version 23.0.1. --- dfu/build.gradle | 4 ++-- dfu/dfu.iml | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/dfu/build.gradle b/dfu/build.gradle index 517dcf0..6010003 100644 --- a/dfu/build.gradle +++ b/dfu/build.gradle @@ -8,7 +8,7 @@ apply plugin: 'com.android.library' android { compileSdkVersion 23 - buildToolsVersion '23.0.0' + buildToolsVersion '23.0.1' defaultConfig { minSdkVersion 18 @@ -26,7 +26,7 @@ android { dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) - compile 'com.android.support:support-v4:23.0.0' + compile 'com.android.support:support-v4:23.0.1' compile 'com.google.code.gson:gson:2.3.1' } diff --git a/dfu/dfu.iml b/dfu/dfu.iml index 2e0d735..e0907d4 100644 --- a/dfu/dfu.iml +++ b/dfu/dfu.iml @@ -72,7 +72,7 @@ - + @@ -91,7 +91,7 @@ - - + + \ No newline at end of file