Option to set Scope in DFU. DFU 1.5.2

Setting scope allows to upload only application from a ZIP that contains
both SD/BL and App. This is useful for Secure DFU when SD/BL update
succeeds but App upload fails. Repeating SD/BL is not possible as the BL
version check fails.
This commit is contained in:
Aleksander Nowakowski
2017-11-03 17:42:22 +01:00
parent a22f9eb17a
commit fec8377db5
7 changed files with 182 additions and 27 deletions

View File

@@ -49,7 +49,7 @@ dependencies {
implementation 'no.nordicsemi.android.support.v18:scanner:1.0.0'
// The DFU Library is imported automatically from jcenter:
implementation 'no.nordicsemi.android:dfu:1.5.1'
implementation 'no.nordicsemi.android:dfu:1.5.2'
// if you desire to build the DFU Library, clone the https://github.com/NordicSemiconductor/Android-DFU-Library project into DFULibrary folder,
// add it as a module into the project structure and uncomment the following line (and also the according lines in the settings.gradle):
// implementation project(':dfu')

View File

@@ -90,6 +90,7 @@ public class DfuActivity extends AppCompatActivity implements LoaderCallbacks<Cu
private static final String PREFS_DEVICE_NAME = "no.nordicsemi.android.nrftoolbox.dfu.PREFS_DEVICE_NAME";
private static final String PREFS_FILE_NAME = "no.nordicsemi.android.nrftoolbox.dfu.PREFS_FILE_NAME";
private static final String PREFS_FILE_TYPE = "no.nordicsemi.android.nrftoolbox.dfu.PREFS_FILE_TYPE";
private static final String PREFS_FILE_SCOPE = "no.nordicsemi.android.nrftoolbox.dfu.PREFS_FILE_SCOPE";
private static final String PREFS_FILE_SIZE = "no.nordicsemi.android.nrftoolbox.dfu.PREFS_FILE_SIZE";
private static final String DATA_DEVICE = "device";
@@ -100,6 +101,7 @@ public class DfuActivity extends AppCompatActivity implements LoaderCallbacks<Cu
private static final String DATA_INIT_FILE_PATH = "init_file_path";
private static final String DATA_INIT_FILE_STREAM = "init_file_stream";
private static final String DATA_STATUS = "status";
private static final String DATA_SCOPE = "scope";
private static final String DATA_DFU_COMPLETED = "dfu_completed";
private static final String DATA_DFU_ERROR = "dfu_error";
@@ -113,6 +115,7 @@ public class DfuActivity extends AppCompatActivity implements LoaderCallbacks<Cu
private TextView mDeviceNameView;
private TextView mFileNameView;
private TextView mFileTypeView;
private TextView mFileScopeView;
private TextView mFileSizeView;
private TextView mFileStatusView;
private TextView mTextPercentage;
@@ -128,6 +131,7 @@ public class DfuActivity extends AppCompatActivity implements LoaderCallbacks<Cu
private Uri mInitFileStreamUri;
private int mFileType;
private int mFileTypeTmp; // This value is being used when user is selecting a file not to overwrite the old value (in case he/she will cancel selecting file)
private Integer mScope;
private boolean mStatusOk;
/** Flag set to true in {@link #onRestart()} and to false in {@link #onPause()}. */
private boolean mResumed;
@@ -264,6 +268,7 @@ public class DfuActivity extends AppCompatActivity implements LoaderCallbacks<Cu
mInitFileStreamUri = savedInstanceState.getParcelable(DATA_INIT_FILE_STREAM);
mSelectedDevice = savedInstanceState.getParcelable(DATA_DEVICE);
mStatusOk = mStatusOk || savedInstanceState.getBoolean(DATA_STATUS);
mScope = savedInstanceState.containsKey(DATA_SCOPE) ? savedInstanceState.getInt(DATA_SCOPE) : null;
mUploadButton.setEnabled(mSelectedDevice != null && mStatusOk);
mDfuCompleted = savedInstanceState.getBoolean(DATA_DFU_COMPLETED);
mDfuError = savedInstanceState.getString(DATA_DFU_ERROR);
@@ -289,6 +294,7 @@ public class DfuActivity extends AppCompatActivity implements LoaderCallbacks<Cu
outState.putParcelable(DATA_INIT_FILE_STREAM, mInitFileStreamUri);
outState.putParcelable(DATA_DEVICE, mSelectedDevice);
outState.putBoolean(DATA_STATUS, mStatusOk);
if (mScope != null) outState.putInt(DATA_SCOPE, mScope);
outState.putBoolean(DATA_DFU_COMPLETED, mDfuCompleted);
outState.putString(DATA_DFU_ERROR, mDfuError);
}
@@ -301,10 +307,10 @@ public class DfuActivity extends AppCompatActivity implements LoaderCallbacks<Cu
mDeviceNameView = findViewById(R.id.device_name);
mFileNameView = findViewById(R.id.file_name);
mFileTypeView = findViewById(R.id.file_type);
mFileScopeView = findViewById(R.id.file_scope);
mFileSizeView = findViewById(R.id.file_size);
mFileStatusView = findViewById(R.id.file_status);
mSelectFileButton = findViewById(R.id.action_select_file);
mUploadButton = findViewById(R.id.action_upload);
mConnectButton = findViewById(R.id.action_connect);
mTextPercentage = findViewById(R.id.textviewProgress);
@@ -317,6 +323,7 @@ public class DfuActivity extends AppCompatActivity implements LoaderCallbacks<Cu
mDeviceNameView.setText(preferences.getString(PREFS_DEVICE_NAME, ""));
mFileNameView.setText(preferences.getString(PREFS_FILE_NAME, ""));
mFileTypeView.setText(preferences.getString(PREFS_FILE_TYPE, ""));
mFileScopeView.setText(preferences.getString(PREFS_FILE_SCOPE, ""));
mFileSizeView.setText(preferences.getString(PREFS_FILE_SIZE, ""));
mFileStatusView.setText(R.string.dfu_file_status_ok);
mStatusOk = true;
@@ -558,23 +565,53 @@ public class DfuActivity extends AppCompatActivity implements LoaderCallbacks<Cu
break;
}
mFileSizeView.setText(getString(R.string.dfu_file_size_text, fileSize));
mFileScopeView.setText(getString(R.string.not_available));
final String extension = mFileType == DfuService.TYPE_AUTO ? "(?i)ZIP" : "(?i)HEX|BIN"; // (?i) = case insensitive
final boolean statusOk = mStatusOk = MimeTypeMap.getFileExtensionFromUrl(fileName).matches(extension);
mFileStatusView.setText(statusOk ? R.string.dfu_file_status_ok : R.string.dfu_file_status_invalid);
mUploadButton.setEnabled(mSelectedDevice != null && statusOk);
// Ask the user for the Init packet file if HEX or BIN files are selected. In case of a ZIP file the Init packets should be included in the ZIP.
if (statusOk && fileType != DfuService.TYPE_AUTO) {
new AlertDialog.Builder(this).setTitle(R.string.dfu_file_init_title).setMessage(R.string.dfu_file_init_message)
.setNegativeButton(R.string.no, (dialog, which) -> {
mInitFilePath = null;
mInitFileStreamUri = null;
}).setPositiveButton(R.string.yes, (dialog, which) -> {
final Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType(DfuService.MIME_TYPE_OCTET_STREAM);
intent.addCategory(Intent.CATEGORY_OPENABLE);
startActivityForResult(intent, SELECT_INIT_FILE_REQ);
}).show();
if (statusOk) {
if (fileType != DfuService.TYPE_AUTO) {
mScope = null;
mFileScopeView.setText(getString(R.string.not_available));
new AlertDialog.Builder(this).setTitle(R.string.dfu_file_init_title).setMessage(R.string.dfu_file_init_message)
.setNegativeButton(R.string.no, (dialog, which) -> {
mInitFilePath = null;
mInitFileStreamUri = null;
}).setPositiveButton(R.string.yes, (dialog, which) -> {
final Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType(DfuService.MIME_TYPE_OCTET_STREAM);
intent.addCategory(Intent.CATEGORY_OPENABLE);
startActivityForResult(intent, SELECT_INIT_FILE_REQ);
}).show();
} else {
new AlertDialog.Builder(this).setTitle(R.string.dfu_file_scope_title).setCancelable(false)
.setSingleChoiceItems(R.array.dfu_file_scope, 0, (dialog, which) -> {
switch (which) {
case 0:
mScope = null;
break;
case 1:
mScope = DfuServiceInitiator.SCOPE_SYSTEM_COMPONENTS;
break;
case 2:
mScope = DfuServiceInitiator.SCOPE_APPLICATION;
break;
}
}).setPositiveButton(R.string.ok, (dialogInterface, i) -> {
int index;
if (mScope == null) {
index = 0;
} else if (mScope == DfuServiceInitiator.SCOPE_SYSTEM_COMPONENTS) {
index = 1;
} else {
index = 2;
}
mFileScopeView.setText(getResources().getStringArray(R.array.dfu_file_scope)[index]);
}).show();
}
}
}
@@ -680,6 +717,7 @@ public class DfuActivity extends AppCompatActivity implements LoaderCallbacks<Cu
editor.putString(PREFS_DEVICE_NAME, mSelectedDevice.getName());
editor.putString(PREFS_FILE_NAME, mFileNameView.getText().toString());
editor.putString(PREFS_FILE_TYPE, mFileTypeView.getText().toString());
editor.putString(PREFS_FILE_SCOPE, mFileScopeView.getText().toString());
editor.putString(PREFS_FILE_SIZE, mFileSizeView.getText().toString());
editor.apply();
@@ -703,9 +741,11 @@ public class DfuActivity extends AppCompatActivity implements LoaderCallbacks<Cu
.setPacketsReceiptNotificationsEnabled(enablePRNs)
.setPacketsReceiptNotificationsValue(numberOfPackets)
.setUnsafeExperimentalButtonlessServiceInSecureDfuEnabled(true);
if (mFileType == DfuService.TYPE_AUTO)
if (mFileType == DfuService.TYPE_AUTO) {
starter.setZip(mFileStreamUri, mFilePath);
else {
if (mScope != null)
starter.setScope(mScope);
} else {
starter.setBinOrHex(mFileType, mFileStreamUri, mFilePath).setInitFile(mInitFileStreamUri, mInitFilePath);
}
starter.start(this, DfuService.class);
@@ -793,6 +833,7 @@ public class DfuActivity extends AppCompatActivity implements LoaderCallbacks<Cu
// Application may have lost the right to these files if Activity was closed during upload (grant uri permission). Clear file related values.
mFileNameView.setText(null);
mFileTypeView.setText(null);
mFileScopeView.setText(null);
mFileSizeView.setText(null);
mFileStatusView.setText(R.string.dfu_file_status_no_file);
mFilePath = null;
@@ -811,7 +852,7 @@ public class DfuActivity extends AppCompatActivity implements LoaderCallbacks<Cu
}
private boolean isDfuServiceRunning() {
ActivityManager manager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
final ActivityManager manager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if (DfuService.class.getName().equals(service.service.getClassName())) {
return true;

View File

@@ -78,7 +78,7 @@
<LinearLayout
style="@style/Widget.List"
android:layout_width="0dp"
android:layout_height="160dp"
android:layout_height="176dp"
android:layout_marginBottom="8dp"
android:layout_marginLeft="4dp"
android:layout_marginTop="@dimen/feature_vertical_margin_top"
@@ -133,6 +133,23 @@
android:freezesText="true"/>
</TableRow>
<TableRow
android:layout_width="match_parent"
android:layout_height="wrap_content">
<no.nordicsemi.android.nrftoolbox.widget.TrebuchetTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/dfu_file_scope_label"/>
<no.nordicsemi.android.nrftoolbox.widget.TrebuchetBoldTextView
android:id="@+id/file_scope"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:freezesText="true"/>
</TableRow>
<TableRow
android:layout_width="match_parent"
android:layout_height="wrap_content">
@@ -173,7 +190,6 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/feature_section_padding"
android:layout_marginTop="4dp"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingLeft="42dp">
@@ -200,7 +216,7 @@
android:id="@+id/dfu_pane"
style="@style/Widget.List"
android:layout_width="0dp"
android:layout_height="160dp"
android:layout_height="176dp"
android:layout_marginBottom="8dp"
android:layout_marginLeft="14dp"
android:layout_marginRight="4dp"
@@ -254,8 +270,7 @@
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="@dimen/feature_horizontal_margin"
android:layout_alignParentRight="true"
android:layout_alignRight="@+id/dfu_container"
android:layout_below="@+id/dfu_container"
android:text="@string/dfu_lib_version"
android:textSize="12dp"/>

View File

@@ -126,6 +126,23 @@
android:freezesText="true"/>
</TableRow>
<TableRow
android:layout_width="match_parent"
android:layout_height="wrap_content">
<no.nordicsemi.android.nrftoolbox.widget.TrebuchetTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/dfu_file_scope_label"/>
<no.nordicsemi.android.nrftoolbox.widget.TrebuchetBoldTextView
android:id="@+id/file_scope"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:freezesText="true"/>
</TableRow>
<TableRow
android:layout_width="match_parent"
android:layout_height="wrap_content">

View File

@@ -148,6 +148,23 @@
android:freezesText="true"/>
</TableRow>
<TableRow
android:layout_width="match_parent"
android:layout_height="wrap_content">
<no.nordicsemi.android.nrftoolbox.widget.TrebuchetTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/dfu_file_scope_label"/>
<no.nordicsemi.android.nrftoolbox.widget.TrebuchetBoldTextView
android:id="@+id/file_scope"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:freezesText="true"/>
</TableRow>
<TableRow
android:layout_width="match_parent"
android:layout_height="wrap_content">

View File

@@ -24,7 +24,7 @@
<string name="dfu_feature_title">DFU</string>
<string name="dfu_service_title">nRF Toolbox DFU Proxy</string>
<string name="dfu_settings_title">DFU Settings</string>
<string name="dfu_lib_version">DFU Library version 1.5.1</string>
<string name="dfu_lib_version">DFU Library version 1.5.2</string>
<string name="dfu_feature_title_long">DEVICE FIRMWARE UPDATE</string>
<dimen name="dfu_feature_title_long_margin">-186dp</dimen>
@@ -34,9 +34,10 @@
<string name="dfu_scripts_created">DFU script files were copied to /sdcard/Nordic Semiconductor.</string>
<string name="dfu_section_application_header">APPLICATION</string>
<string name="dfu_file_name_label">File Name:</string>
<string name="dfu_file_type_label">File Type:</string>
<string name="dfu_file_size_label">File Size:</string>
<string name="dfu_file_name_label">File name:</string>
<string name="dfu_file_type_label">Type:</string>
<string name="dfu_file_size_label">Size:</string>
<string name="dfu_file_scope_label">Scope:</string>
<string name="dfu_file_status_label">Status:</string>
<string name="dfu_file_size_text">%d bytes</string>
<string name="dfu_file_status_ok">OK</string>
@@ -83,7 +84,7 @@
<string name="dfu_settings_dfu_number_of_packets_info">During a DFU operation a lot of data packets are being sent to the target. The <i>onCharacteristicWrite(...)</i>
callback in Android API is invoked when the data has been written to the outgoing queue, not when physically sent. Packet receipt notifications were introduced to
prevent from overflowing the queue. Depending on the device model, disabling the notifications or setting the value to “high” (> ~300) may make the DFU process freeze
at some point.</string>
at some point on Android versions before Marshmallow.</string>
<string name="dfu_file_type_title">Select file type</string>
<string-array name="dfu_file_type">
@@ -97,6 +98,12 @@
The Init packet file (*.dat) should contain the device type and revision, application version, list of supported Soft Devices and the firmware CRC
in binary format or, with old versions of the DFU bootloader, only the CRC (CRC-CCITT-16).
With the new version of the bootloader the extended Init packet is <b>required</b>.</string>
<string name="dfu_file_scope_title">Select scope</string>
<string-array name="dfu_file_scope">
<item>All</item>
<item>System components only</item>
<item>Application only</item>
</string-array>
<string name="dfu_unknown_name">unnamed device</string>
<string name="dfu_uploading_percentage_label">0%</string>
@@ -110,7 +117,7 @@
<string name="dfu_help_title">Select file</string>
<string name="dfu_help_message">A file browser application must be installed on the device before selecting the file.
\n\nThere are number of applications available on Google Play store, e.g. Total Commander or File Manager, that allow you to pick a file from internal memory of the device. To upload
a file from the Internet you may use f.e. Drive or Dropbox application.
a file from the Internet you may use e.g. Drive or Dropbox application.
\n\nYou will be asked to select an application if more than one is installed. A single application will be launched automatically.
\n\nSince <b>Android KitKat</b> you may use the preinstalled document picker application. Ensure <i>Display advanced devices</i> option is enabled in settings to use the <i>Internal storage</i>.
\n\nSample applications were copied to <i>Nordic Semiconductor</i> folder in the internal storage.</string>

View File

@@ -0,0 +1,58 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ 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.
-->
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
<PreferenceCategory android:title="@string/dfu_settings_dfu" >
<SwitchPreference
android:defaultValue="false"
android:key="settings_packet_receipt_notification_enabled"
android:title="@string/dfu_settings_dfu_packets_receipt_notification_label" />
<EditTextPreference
android:defaultValue="12"
android:dependency="settings_packet_receipt_notification_enabled"
android:inputType="number"
android:key="settings_number_of_packets"
android:title="@string/dfu_settings_dfu_number_of_packets_label" />
<EditTextPreference
android:defaultValue="4096"
android:inputType="number"
android:key="settings_mbr_size"
android:dialogTitle="@string/dfu_settings_dfu_mbr_size_title"
android:title="@string/dfu_settings_dfu_mbr_size" />
<SwitchPreference
android:defaultValue="false"
android:key="settings_keep_bond"
android:title="@string/dfu_settings_dfu_keep_bond" />
<SwitchPreference
android:defaultValue="false"
android:key="settings_assume_dfu_mode"
android:title="@string/dfu_settings_dfu_assume_dfu_mode" />
<no.nordicsemi.android.nrftoolbox.dfu.settings.AboutDfuPreference
android:summary="@string/dfu_settings_dfu_about_summary"
android:title="@string/dfu_settings_dfu_about" />
</PreferenceCategory>
</PreferenceScreen>