Skip to content

Commit

Permalink
Merge pull request #630 from AltBeacon/improve-data-copy
Browse files Browse the repository at this point in the history
Improve `Beacon` data copy
  • Loading branch information
davidgyoung authored Dec 16, 2017
2 parents 9dd917e + deaa42d commit f221213
Show file tree
Hide file tree
Showing 6 changed files with 266 additions and 43 deletions.
8 changes: 6 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ Bug Fixes:
- Fix NPE on ExtraBeaconDataTracker (#626, David G. Young)
- Fix regression with `RunningAverageRssiFilter.setSampleExpirationMilliseconds`
being overwritten when committing ranged beacon measurements. (#629, Aaron Kromer)
- Fix missing running average RSSI in callbacks when apps do not use the
scheduled scan job feature. (#630, Aaron Kromer)
- Fix copying of multi-frame beacon flag in `Beacon(Beacon)` constructor (#630, Aaron Kromer)
- Fix the `AltBeaon(Beacon)` copy constructor which omitted some data fields (#630, Aaron Kromer)

### 2.12.3 / 2017-10-14

Expand All @@ -15,7 +19,7 @@ Bug Fixes:
Bug Fixes:
- Fix NullPointerException in ProcessUtils. (#598, David G. Young)
- Fix ConcurrentModificationException crashing app on Android 8 when monitored regions are
changed at the same time the app shifts from active scanning to passive scanning.
changed at the same time the app shifts from active scanning to passive scanning.
(#578, David G. Young)
- Fix ConcurrentModifictionExceptions starting ScanJobs. (#584, #588, David G. Young)
- Fix NullPointerException when BluetoothLeScanner cannot be obtained.
Expand Down Expand Up @@ -52,7 +56,7 @@ Bug Fixes:
[Full Changelog](https://github.com/AltBeacon/android-beacon-library/compare/2.11...2.12)

Enhancements:
- Add Android O support with ScanJob using JobScheduler to do scans instead of BeaconService,
- Add Android O support with ScanJob using JobScheduler to do scans instead of BeaconService,
set as default for Android O. (#484, David G. Young)

Bug Fixes:
Expand Down
10 changes: 2 additions & 8 deletions src/main/java/org/altbeacon/beacon/AltBeacon.java
Original file line number Diff line number Diff line change
Expand Up @@ -64,20 +64,14 @@ public AltBeacon[] newArray(int size) {
* @param beacon
*/
protected AltBeacon(Beacon beacon) {
super();
this.mBluetoothAddress = beacon.mBluetoothAddress;
this.mIdentifiers = beacon.mIdentifiers;
this.mBeaconTypeCode = beacon.mBeaconTypeCode;
this.mDataFields = beacon.mDataFields;
this.mDistance = beacon.mDistance;
this.mRssi = beacon.mRssi;
this.mTxPower = beacon.mTxPower;
super(beacon);
}

/**
* @see AltBeacon.Builder to make AltBeacon instances
*/
protected AltBeacon() {
super();
}

/**
Expand Down
2 changes: 2 additions & 0 deletions src/main/java/org/altbeacon/beacon/Beacon.java
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,8 @@ protected Beacon(Beacon otherBeacon) {
this.mServiceUuid = otherBeacon.getServiceUuid();
this.mBluetoothName = otherBeacon.mBluetoothName;
this.mParserIdentifier = otherBeacon.mParserIdentifier;
this.mMultiFrameBeacon = otherBeacon.mMultiFrameBeacon;
this.mManufacturer = otherBeacon.mManufacturer;
}

/**
Expand Down
159 changes: 128 additions & 31 deletions src/test/java/org/altbeacon/beacon/AltBeaconTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,20 @@

import android.os.Parcel;

import static org.junit.Assert.assertEquals;

import org.altbeacon.beacon.logging.Loggers;
import org.robolectric.RobolectricTestRunner;

import org.junit.runner.RunWith;
import org.junit.After;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;

import java.util.Arrays;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.allOf;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasProperty;
import static org.junit.Assert.assertEquals;

@Config(sdk = 18)

@RunWith(RobolectricTestRunner.class)
Expand All @@ -26,36 +31,128 @@
4. Expand the System.err section
*/
public class AltBeaconTest {
private Parcel aParcel = null;

public static byte[] hexStringToByteArray(String s) {
int len = s.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
+ Character.digit(s.charAt(i+1), 16));
}
return data;
}

@Test
public void testRecognizeBeacon() {
byte[] bytes = hexStringToByteArray("02011a1bff1801beac2f234454cf6d4a0fadf2f4911ba9ffa600010002c509");
AltBeaconParser parser = new AltBeaconParser();
Beacon beacon = parser.fromScanData(bytes, -55, null);
assertEquals("manData should be parsed", 9, ((AltBeacon) beacon).getMfgReserved() );
}
@After
public void after() {
// Clean up any obtained parcel
if (null != aParcel) {
aParcel.recycle();
}
}

public static byte[] hexStringToByteArray(String s) {
int len = s.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
+ Character.digit(s.charAt(i+1), 16));
}
return data;
}

@Test
public void testRecognizeBeacon() {
byte[] bytes = hexStringToByteArray("02011a1bff1801beac2f234454cf6d4a0fadf2f4911ba9ffa600010002c509");
AltBeaconParser parser = new AltBeaconParser();
Beacon beacon = parser.fromScanData(bytes, -55, null);
assertEquals("manData should be parsed", 9, ((AltBeacon) beacon).getMfgReserved() );
}

@Test
public void testCanSerializeParcelable() {
org.robolectric.shadows.ShadowLog.stream = System.err;
Parcel parcel = Parcel.obtain();
Beacon beacon = new AltBeacon.Builder().setMfgReserved(7).setId1("1").setId2("2").setId3("3").setRssi(4)
.setBeaconTypeCode(5).setTxPower(6)
.setBluetoothAddress("1:2:3:4:5:6").build();
beacon.writeToParcel(parcel, 0);
parcel.setDataPosition(0);
Beacon beacon2 = new AltBeacon(parcel);
assertEquals("beaconMfgReserved is same after deserialization", ((AltBeacon)beacon).getMfgReserved(), ((AltBeacon)beacon2).getMfgReserved());
final Beacon original = new AltBeacon.Builder().setMfgReserved(2)
.setBluetoothAddress("aa:bb:cc:dd:ee:ff")
.setBluetoothName("Any Bluetooth")
.setBeaconTypeCode(1)
.setExtraDataFields(Arrays.asList(4L, 5L))
.setId1("6")
.setId2("7")
.setId3("8")
.setManufacturer(10)
.setMultiFrameBeacon(true)
.setParserIdentifier("Any Parser ID")
.setRssi(-11)
.setRunningAverageRssi(-12.3)
.setServiceUuid(13)
.setTxPower(14)
.build();
original.setPacketCount(15);
original.setRssiMeasurementCount(16);

aParcel = Parcel.obtain();
original.writeToParcel(aParcel, 0);
aParcel.setDataPosition(0);
final AltBeacon parceled = AltBeacon.CREATOR.createFromParcel(aParcel);
assertThat(
parceled,
allOf(
hasProperty("bluetoothAddress", equalTo("aa:bb:cc:dd:ee:ff")),
hasProperty("bluetoothName", equalTo("Any Bluetooth")),
hasProperty("beaconTypeCode", equalTo(1)),
hasProperty("dataFields", equalTo(Arrays.asList(2L))),
hasProperty("extraDataFields", equalTo(Arrays.asList(4L, 5L))),
hasProperty("id1", equalTo(Identifier.fromInt(6))),
hasProperty("id2", equalTo(Identifier.fromInt(7))),
hasProperty("id3", equalTo(Identifier.fromInt(8))),
hasProperty("manufacturer", equalTo(10)),
hasProperty("multiFrameBeacon", equalTo(true)),
hasProperty("parserIdentifier", equalTo("Any Parser ID")),
hasProperty("rssi", equalTo(-11)),
hasProperty("runningAverageRssi", equalTo(-12.3)),
hasProperty("serviceUuid", equalTo(13)),
hasProperty("txPower", equalTo(14)),
hasProperty("mfgReserved", equalTo(2)),
hasProperty("packetCount", equalTo(15)),
hasProperty("measurementCount", equalTo(16))
)
);
}


@Test
public void copyingBeaconTransfersAllFields() {
final Beacon original = new AltBeacon.Builder().setMfgReserved(2)
.setBluetoothAddress("aa:bb:cc:dd:ee:ff")
.setBluetoothName("Any Bluetooth")
.setBeaconTypeCode(1)
.setExtraDataFields(Arrays.asList(4L, 5L))
.setId1("6")
.setId2("7")
.setId3("8")
.setManufacturer(10)
.setMultiFrameBeacon(true)
.setParserIdentifier("Any Parser ID")
.setRssi(-11)
.setRunningAverageRssi(-12.3)
.setServiceUuid(13)
.setTxPower(14)
.build();
original.setPacketCount(15);
original.setRssiMeasurementCount(16);
final AltBeacon copied = new AltBeacon(original);
assertThat(
copied,
allOf(
hasProperty("bluetoothAddress", equalTo("aa:bb:cc:dd:ee:ff")),
hasProperty("bluetoothName", equalTo("Any Bluetooth")),
hasProperty("beaconTypeCode", equalTo(1)),
hasProperty("dataFields", equalTo(Arrays.asList(2L))),
hasProperty("extraDataFields", equalTo(Arrays.asList(4L, 5L))),
hasProperty("id1", equalTo(Identifier.fromInt(6))),
hasProperty("id2", equalTo(Identifier.fromInt(7))),
hasProperty("id3", equalTo(Identifier.fromInt(8))),
hasProperty("manufacturer", equalTo(10)),
hasProperty("multiFrameBeacon", equalTo(true)),
hasProperty("parserIdentifier", equalTo("Any Parser ID")),
hasProperty("rssi", equalTo(-11)),
hasProperty("runningAverageRssi", equalTo(-12.3)),
hasProperty("serviceUuid", equalTo(13)),
hasProperty("txPower", equalTo(14)),
hasProperty("packetCount", equalTo(15)),
hasProperty("measurementCount", equalTo(16))
)
);
}
}
113 changes: 113 additions & 0 deletions src/test/java/org/altbeacon/beacon/BeaconTest.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
package org.altbeacon.beacon;

import android.os.Parcel;

import org.altbeacon.beacon.distance.ModelSpecificDistanceCalculator;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.allOf;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasProperty;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

Expand Down Expand Up @@ -35,11 +42,21 @@
4. Expand the System.err section
*/
public class BeaconTest {
private Parcel aParcel = null;

@Before
public void before() {
Beacon.setHardwareEqualityEnforced(false);
}

@After
public void after() {
// Clean up any obtained parcel
if (null != aParcel) {
aParcel.recycle();
}
}

@Test
public void testAccessBeaconIdentifiers() {
Beacon beacon = new AltBeacon.Builder().setMfgReserved(7).setId1("1").setId2("2").setId3("3").setRssi(4)
Expand Down Expand Up @@ -206,6 +223,102 @@ public void testHashCodeWithNullIdentifier() {
.build();
assertTrue("hashCode() should not throw exception", beacon.hashCode() >= Integer.MIN_VALUE);
}

@Test
public void parcelingBeaconContainsAllFields() {
final Beacon original = new Beacon.Builder().setBluetoothAddress("aa:bb:cc:dd:ee:ff")
.setBluetoothName("Any Bluetooth")
.setBeaconTypeCode(1)
.setDataFields(Arrays.asList(2L, 3L))
.setExtraDataFields(Arrays.asList(4L, 5L))
.setId1("6")
.setId2("7")
.setId3("8")
.setManufacturer(10)
.setMultiFrameBeacon(true)
.setParserIdentifier("Any Parser ID")
.setRssi(-11)
.setRunningAverageRssi(-12.3)
.setServiceUuid(13)
.setTxPower(14)
.build();
original.setPacketCount(15);
original.setRssiMeasurementCount(16);

aParcel = Parcel.obtain();
original.writeToParcel(aParcel, 0);
aParcel.setDataPosition(0);
final Beacon parceled = Beacon.CREATOR.createFromParcel(aParcel);
assertThat(
parceled,
allOf(
hasProperty("bluetoothAddress", equalTo("aa:bb:cc:dd:ee:ff")),
hasProperty("bluetoothName", equalTo("Any Bluetooth")),
hasProperty("beaconTypeCode", equalTo(1)),
hasProperty("dataFields", equalTo(Arrays.asList(2L, 3L))),
hasProperty("extraDataFields", equalTo(Arrays.asList(4L, 5L))),
hasProperty("id1", equalTo(Identifier.fromInt(6))),
hasProperty("id2", equalTo(Identifier.fromInt(7))),
hasProperty("id3", equalTo(Identifier.fromInt(8))),
hasProperty("manufacturer", equalTo(10)),
hasProperty("multiFrameBeacon", equalTo(true)),
hasProperty("parserIdentifier", equalTo("Any Parser ID")),
hasProperty("rssi", equalTo(-11)),
hasProperty("runningAverageRssi", equalTo(-12.3)),
hasProperty("serviceUuid", equalTo(13)),
hasProperty("txPower", equalTo(14)),
hasProperty("packetCount", equalTo(15)),
hasProperty("measurementCount", equalTo(16))
)
);
}

@Test
public void copyingBeaconContainsAllFields() {
final Beacon original = new Beacon.Builder().setBluetoothAddress("aa:bb:cc:dd:ee:ff")
.setBluetoothName("Any Bluetooth")
.setBeaconTypeCode(1)
.setDataFields(Arrays.asList(2L, 3L))
.setExtraDataFields(Arrays.asList(4L, 5L))
.setId1("6")
.setId2("7")
.setId3("8")
.setManufacturer(10)
.setMultiFrameBeacon(true)
.setParserIdentifier("Any Parser ID")
.setRssi(-11)
.setRunningAverageRssi(-12.3)
.setServiceUuid(13)
.setTxPower(14)
.build();
original.setPacketCount(15);
original.setRssiMeasurementCount(16);

final Beacon copied = new Beacon(original);
assertThat(
copied,
allOf(
hasProperty("bluetoothAddress", equalTo("aa:bb:cc:dd:ee:ff")),
hasProperty("bluetoothName", equalTo("Any Bluetooth")),
hasProperty("beaconTypeCode", equalTo(1)),
hasProperty("dataFields", equalTo(Arrays.asList(2L, 3L))),
hasProperty("extraDataFields", equalTo(Arrays.asList(4L, 5L))),
hasProperty("id1", equalTo(Identifier.fromInt(6))),
hasProperty("id2", equalTo(Identifier.fromInt(7))),
hasProperty("id3", equalTo(Identifier.fromInt(8))),
hasProperty("manufacturer", equalTo(10)),
hasProperty("multiFrameBeacon", equalTo(true)),
hasProperty("parserIdentifier", equalTo("Any Parser ID")),
hasProperty("rssi", equalTo(-11)),
hasProperty("runningAverageRssi", equalTo(-12.3)),
hasProperty("serviceUuid", equalTo(13)),
hasProperty("txPower", equalTo(14)),
hasProperty("packetCount", equalTo(15)),
hasProperty("measurementCount", equalTo(16))
)
);
}

// utilty methods for testing serialization

private byte[] convertToBytes(Object object) throws IOException {
Expand Down
Loading

0 comments on commit f221213

Please sign in to comment.