Skip to content

Commit c67c55d

Browse files
committed
modify locks
1 parent 6e3e57b commit c67c55d

File tree

2 files changed

+93
-59
lines changed

2 files changed

+93
-59
lines changed

src/main/AndroidManifest.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
22
package="org.microbit.partialflashing"
33
android:versionCode="1"
4-
android:versionName="1.0" >
4+
android:versionName="1.1" >
55

66
<uses-permission android:name="android.permission.BLUETOOTH" />
77
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />

src/main/java/org/microbit/android/partialflashing/PartialFlashingBaseService.java

Lines changed: 92 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
import android.content.Context;
1616
import android.content.Intent;
1717
import android.content.IntentFilter;
18-
import android.os.Handler;
1918
import android.os.SystemClock;
2019
import android.util.Log;
2120

@@ -37,6 +36,8 @@
3736
// A service that interacts with the BLE device via the Android BLE API.
3837
public abstract class PartialFlashingBaseService extends IntentService {
3938

39+
public static final String DFU_BROADCAST_ERROR = "no.nordicsemi.android.dfu.broadcast.BROADCAST_ERROR";
40+
4041
public static final UUID PARTIAL_FLASH_CHARACTERISTIC = UUID.fromString("e97d3b10-251d-470a-a062-fa1922dfa9a8");
4142
public static final UUID PARTIAL_FLASHING_SERVICE = UUID.fromString("e97dd91d-251d-470a-a062-fa1922dfa9a8");
4243
public static final String PXT_MAGIC = "708E3B92C615A841C49866C975EE5197";
@@ -54,16 +55,15 @@ public abstract class PartialFlashingBaseService extends IntentService {
5455
private BluetoothGatt mBluetoothGatt;
5556
private int mConnectionState = STATE_DISCONNECTED;
5657
private BluetoothDevice device;
57-
BluetoothGattService Service;
58-
BluetoothGattService dfuService;
59-
60-
BluetoothGattCharacteristic partialFlashCharacteristic;
6158

6259
private final Object lock = new Object();
60+
private final Object region_lock = new Object();
6361

6462
private static final byte PACKET_STATE_WAITING = 0;
6563
private static final byte PACKET_STATE_SENT = (byte)0xFF;
6664
private static final byte PACKET_STATE_RETRANSMIT = (byte)0xAA;
65+
private static final byte PACKET_STATE_COMPLETE_FLASH = (byte) 0xCF;
66+
6767
private byte packetState = PACKET_STATE_WAITING;
6868

6969
// Used to lock the program state while we wait for a Bluetooth operation to complete
@@ -151,17 +151,6 @@ public void onServicesDiscovered(BluetoothGatt gatt, int status) {
151151
} else {
152152
Log.w(TAG, "onServicesDiscovered received: " + status);
153153
}
154-
155-
Service = gatt.getService(PARTIAL_FLASHING_SERVICE);
156-
if (Service == null) {
157-
Log.e(TAG, "pf service not found!");
158-
}
159-
160-
dfuService = gatt.getService(MICROBIT_DFU_SERVICE);
161-
if (dfuService == null) {
162-
Log.e(TAG, "dfu service not found!");
163-
}
164-
165154
synchronized (lock) {
166155
lock.notifyAll();
167156
}
@@ -187,7 +176,7 @@ public void onCharacteristicWrite(BluetoothGatt gatt,
187176
Log.v(TAG, "GATT status: Success");
188177
} else {
189178
// TODO Attempt to resend?
190-
Log.v(TAG, "GATT status:" + Integer.toString(status));
179+
Log.v(TAG, "GATT WRITE ERROR. status:" + Integer.toString(status));
191180
}
192181
synchronized (lock) {
193182
lock.notifyAll();
@@ -218,16 +207,19 @@ public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteris
218207
if (notificationValue[1] == REGION_DAL)
219208
dalHash = bytesToHex(hash);
220209

210+
synchronized (region_lock) {
211+
region_lock.notifyAll();
212+
}
213+
221214
break;
222215
}
223216
case FLASH_COMMAND: {
224217
packetState = notificationValue[1];
218+
synchronized (lock) {
219+
lock.notifyAll();
220+
}
225221
}
226222
}
227-
228-
synchronized (lock) {
229-
lock.notifyAll();
230-
}
231223
}
232224

233225
@Override
@@ -285,8 +277,7 @@ private void sendProgressBroadcastComplete() {
285277
}
286278

287279
// Write to BLE Flash Characteristic
288-
public Boolean writePartialFlash(byte data[]){
289-
280+
public Boolean writePartialFlash(BluetoothGattCharacteristic partialFlashCharacteristic, byte[] data){
290281
partialFlashCharacteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE);
291282
partialFlashCharacteristic.setValue(data);
292283
boolean status = mBluetoothGatt.writeCharacteristic(partialFlashCharacteristic);
@@ -302,6 +293,8 @@ public int attemptPartialFlash(String filePath) {
302293
int progressBar = 0;
303294
int numOfLines = 0;
304295

296+
sendProgressBroadcastStart();
297+
305298
try {
306299

307300
Log.v(TAG, "attemptPartialFlash()");
@@ -323,14 +316,21 @@ public int attemptPartialFlash(String filePath) {
323316
Log.v(TAG, "Total lines: " + numOfLines);
324317

325318
// Ready to flash!
326-
sendProgressBroadcastStart();
327319
// Loop through data
328320
String hexData;
329321
int packetNum = 0;
330322
int lineCount = 0;
323+
324+
// Characteristic
325+
BluetoothGattService pfService = mBluetoothGatt.getService(PARTIAL_FLASHING_SERVICE);
326+
BluetoothGattCharacteristic partialFlashCharacteristic = pfService.getCharacteristic(PARTIAL_FLASH_CHARACTERISTIC);
327+
331328
while(true){
332-
// Timeout if total is > 60 seconds
333-
if(SystemClock.elapsedRealtime() - startTime > 60000) return PF_FAILED;
329+
// Timeout if total is > 30 seconds
330+
if(SystemClock.elapsedRealtime() - startTime > 60000) {
331+
Log.v(TAG, "Partial flashing has timed out");
332+
return PF_FAILED;
333+
}
334334

335335
// Get next data to write
336336
hexData = hex.getDataFromIndex(magicIndex + lineCount);
@@ -354,7 +354,7 @@ public int attemptPartialFlash(String filePath) {
354354

355355
// Write without response
356356
// Wait for previous write to complete
357-
boolean writeStatus = writePartialFlash(chunk);
357+
boolean writeStatus = writePartialFlash(partialFlashCharacteristic, chunk);
358358

359359
// Sleep after 4 packets
360360
count++;
@@ -371,11 +371,11 @@ public int attemptPartialFlash(String filePath) {
371371
long timeout = SystemClock.elapsedRealtime();
372372
while(packetState == PACKET_STATE_WAITING) {
373373
synchronized (lock) {
374-
lock.wait(1);
374+
lock.wait(5000);
375375
}
376376

377377
// Timeout if longer than 5 seconds
378-
if((SystemClock.elapsedRealtime() - timeout) > 5000) return PF_FAILED;
378+
if((SystemClock.elapsedRealtime() - timeout) > 5000)return PF_FAILED;
379379
}
380380

381381
packetState = PACKET_STATE_WAITING;
@@ -404,10 +404,11 @@ public int attemptPartialFlash(String filePath) {
404404

405405
// Write End of Flash packet
406406
byte[] endOfFlashPacket = {(byte)0x02};
407-
writePartialFlash(endOfFlashPacket);
407+
writePartialFlash(partialFlashCharacteristic, endOfFlashPacket);
408408

409409
// Finished Writing
410410
Log.v(TAG, "Flash Complete");
411+
packetState = PACKET_STATE_COMPLETE_FLASH;
411412
sendProgressBroadcast(100);
412413
sendProgressBroadcastComplete();
413414

@@ -456,7 +457,7 @@ private boolean initialize(String deviceId) throws InterruptedException {
456457
device = mBluetoothAdapter.getRemoteDevice(deviceId);
457458
}
458459

459-
mBluetoothGatt = device.connectGatt(this, false, mGattCallback);
460+
mBluetoothGatt = device.connectGatt(this, true, mGattCallback);
460461

461462
//check mBluetoothGatt is available
462463
if (mBluetoothGatt == null) {
@@ -469,8 +470,14 @@ private boolean initialize(String deviceId) throws InterruptedException {
469470
}
470471

471472
// Get Characteristic
472-
partialFlashCharacteristic = Service.getCharacteristic(PARTIAL_FLASH_CHARACTERISTIC);
473+
BluetoothGattService pfService = mBluetoothGatt.getService(PARTIAL_FLASHING_SERVICE);
473474

475+
if(pfService == null) {
476+
// Probably not in pairing mode
477+
return false;
478+
}
479+
480+
BluetoothGattCharacteristic partialFlashCharacteristic = pfService.getCharacteristic(PARTIAL_FLASH_CHARACTERISTIC);
474481

475482
// Set up BLE notification
476483
if(!mBluetoothGatt.setCharacteristicNotification(partialFlashCharacteristic, true)){
@@ -479,25 +486,19 @@ private boolean initialize(String deviceId) throws InterruptedException {
479486
Log.v(TAG, "Notifications enabled");
480487
}
481488

482-
// Set up BLE priority
483-
if(mBluetoothGatt.requestConnectionPriority(BluetoothGatt.CONNECTION_PRIORITY_HIGH)){
484-
Log.w(TAG, "Failed to set up priority");
485-
} else {
486-
Log.v(TAG, "High priority");
487-
}
488-
489489
BluetoothGattDescriptor descriptor = partialFlashCharacteristic.getDescriptor(CLIENT_CHARACTERISTIC_CONFIG);
490490
descriptor.setValue(ENABLE_NOTIFICATION_VALUE);
491491
boolean res = mBluetoothGatt.writeDescriptor(descriptor);
492492

493493
synchronized (lock) {
494-
lock.wait(2000);
494+
lock.wait();
495495
}
496496

497497
return true;
498498
}
499-
499+
500500
public static final String BROADCAST_PF_FAILED = "org.microbit.android.partialflashing.broadcast.BROADCAST_PF_FAILED";
501+
public static final String BROADCAST_PF_ATTEMPT_DFU = "org.microbit.android.partialflashing.broadcast.BROADCAST_PF_ATTEMPT_DFU";
501502

502503
@Override
503504
protected void onHandleIntent(@Nullable Intent intent) {
@@ -507,31 +508,52 @@ protected void onHandleIntent(@Nullable Intent intent) {
507508
final String deviceAddress = intent.getStringExtra("deviceAddress");
508509

509510
Log.v(TAG, "Initialise");
511+
boolean initialize_ret = false;
510512
try {
511-
initialize(deviceAddress);
513+
initialize_ret = initialize(deviceAddress);
512514
} catch (InterruptedException e) {
513515
e.printStackTrace();
514516
}
515517
Log.v(TAG, "/Initialise");
516-
readMemoryMap();
518+
517519
// If fails attempt full flash
520+
if(!initialize_ret) {
521+
// Partial flashing started but failed. Need to PF or USB flash to fix
522+
final Intent broadcast = new Intent(BROADCAST_PF_FAILED);
523+
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast);
524+
return;
525+
}
526+
527+
// Get Memory Map from Microbit
528+
try {
529+
readMemoryMap();
530+
} catch (InterruptedException e) {
531+
e.printStackTrace();
532+
}
518533
int pf_result = attemptPartialFlash(filePath);
519-
if((pf_result == PF_ATTEMPT_DFU) || Service == null)
534+
if(pf_result == PF_ATTEMPT_DFU)
520535
{
521536
Log.v(TAG, "Partial Flashing not possible");
522-
537+
BluetoothGattService dfuService = mBluetoothGatt.getService(MICROBIT_DFU_SERVICE);
523538
// Write Characteristic to enter DFU mode
539+
if(dfuService == null) {
540+
Log.v(TAG, "DFU Service is null");
541+
final Intent broadcast = new Intent(DFU_BROADCAST_ERROR);
542+
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast);
543+
return;
544+
}
524545
BluetoothGattCharacteristic microbitDFUCharacteristic = dfuService.getCharacteristic(MICROBIT_DFU_CHARACTERISTIC);
525546
byte payload[] = {0x01};
526547
microbitDFUCharacteristic.setValue(payload);
527548
boolean status = mBluetoothGatt.writeCharacteristic(microbitDFUCharacteristic);
528549
Log.v(TAG, "MicroBitDFU :: Enter DFU Result " + status);
529550

530-
// Wait
531-
try {
532-
Thread.sleep(500);
533-
} catch (InterruptedException e) {
534-
e.printStackTrace();
551+
synchronized (lock) {
552+
try {
553+
lock.wait();
554+
} catch (InterruptedException e) {
555+
e.printStackTrace();
556+
}
535557
}
536558

537559
// Refresh services
@@ -545,13 +567,21 @@ protected void onHandleIntent(@Nullable Intent intent) {
545567
// Log it
546568
}
547569

548-
final Intent broadcast = new Intent(BROADCAST_PF_FAILED);
549-
570+
Log.v(TAG, "Send Intent: BROADCAST_PF_ATTEMPT_DFU");
571+
final Intent broadcast = new Intent(BROADCAST_PF_ATTEMPT_DFU);
550572
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast);
573+
return;
551574
} else if(pf_result == PF_FAILED) {
552575
// Partial flashing started but failed. Need to PF or USB flash to fix
553576
final Intent broadcast = new Intent(BROADCAST_PF_FAILED);
554-
startActivity(broadcast);
577+
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast);
578+
return;
579+
}
580+
581+
// Check complete before leaving intent
582+
if(packetState != PACKET_STATE_COMPLETE_FLASH) {
583+
final Intent broadcast = new Intent(BROADCAST_PF_FAILED);
584+
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast);
555585
}
556586

557587
Log.v(TAG, "onHandleIntent End");
@@ -560,22 +590,26 @@ protected void onHandleIntent(@Nullable Intent intent) {
560590
/*
561591
Read Memory Map from the MB
562592
*/
563-
private Boolean readMemoryMap() {
593+
private Boolean readMemoryMap() throws InterruptedException {
564594
boolean status; // Gatt Status
565595

596+
BluetoothGattService pfService = mBluetoothGatt.getService(PARTIAL_FLASHING_SERVICE);
597+
BluetoothGattCharacteristic partialFlashCharacteristic = pfService.getCharacteristic(PARTIAL_FLASH_CHARACTERISTIC);
598+
566599
try {
567600
for (int i = 0; i < 3; i++)
568601
{
569602
// Get Start, End, and Hash of each Region
570603
// Request Region
571604
byte[] payload = {REGION_INFO_COMMAND, (byte)i};
572605
partialFlashCharacteristic.setValue(payload);
573-
notificationReceived = false;
574606
status = mBluetoothGatt.writeCharacteristic(partialFlashCharacteristic);
575-
Log.v(TAG, "Request Region " + i);
576-
synchronized (lock) {
577-
lock.wait();
607+
Log.v(TAG, "Request Region " + i + " Status: " + status);
608+
609+
synchronized (region_lock) {
610+
region_lock.wait();
578611
}
612+
579613
}
580614

581615

0 commit comments

Comments
 (0)