Merge changes from topics "presubmit-am-2d43f693904f4e0b905048db5b06fbb9", "presubmit-am-4c8a87f356f548f383fd0845aecc022d", "presubmit-am-9ed775d7532a4390a37558866487d8e9", "presubmit-am-9fcce12d783049f788a644fa78e9675f" into tm-mainline-prod

* changes:
  Fix DE index to spec
  Apply ChreDiscoveryProvider fix
  Enable Test App to use Presence Mainline API.
  Filter encryption key tag in PresenceDiscoveryResult
This commit is contained in:
Xinyi Zhou 2022-08-25 01:50:24 +00:00 • committed by Android (Google) Code Review
commit c43c69bbb6
11 changed files with 215 additions and 103 deletions

View file

@ -42,7 +42,6 @@ public final class DataElement implements Parcelable {
/** @hide */
@IntDef({
DataType.BLE_SERVICE_DATA,
DataType.ACCOUNT_KEY,
DataType.BLE_ADDRESS,
DataType.SALT,
DataType.PRIVATE_IDENTITY,
@ -50,27 +49,28 @@ public final class DataElement implements Parcelable {
DataType.PUBLIC_IDENTITY,
DataType.PROVISIONED_IDENTITY,
DataType.TX_POWER,
DataType.INTENT,
DataType.ACTION,
DataType.MODEL_ID,
DataType.FINDER_EPHEMERAL_IDENTIFIER,
DataType.EDDYSTONE_EPHEMERAL_IDENTIFIER,
DataType.ACCOUNT_KEY_DATA,
DataType.CONNECTION_STATUS,
DataType.BATTERY
})
public @interface DataType {
int BLE_SERVICE_DATA = 0;
int ACCOUNT_KEY = 1;
int BLE_ADDRESS = 2;
int SALT = 3;
int PRIVATE_IDENTITY = 4;
int TRUSTED_IDENTITY = 5;
int PUBLIC_IDENTITY = 6;
int PROVISIONED_IDENTITY = 7;
int TX_POWER = 8;
int INTENT = 9;
int MODEL_ID = 10;
int FINDER_EPHEMERAL_IDENTIFIER = 11;
int CONNECTION_STATUS = 12;
int BATTERY = 13;
int BLE_SERVICE_DATA = 100;
int BLE_ADDRESS = 101;
int SALT = 0;
int PRIVATE_IDENTITY = 1;
int TRUSTED_IDENTITY = 2;
int PUBLIC_IDENTITY = 3;
int PROVISIONED_IDENTITY = 4;
int TX_POWER = 5;
int ACTION = 6;
int MODEL_ID = 7;
int EDDYSTONE_EPHEMERAL_IDENTIFIER = 8;
int ACCOUNT_KEY_DATA = 9;
int CONNECTION_STATUS = 10;
int BATTERY = 11;
}
/**
@ -78,7 +78,7 @@ public final class DataElement implements Parcelable {
*/
public static boolean isValidType(int type) {
return type == DataType.BLE_SERVICE_DATA
|| type == DataType.ACCOUNT_KEY
|| type == DataType.ACCOUNT_KEY_DATA
|| type == DataType.BLE_ADDRESS
|| type == DataType.SALT
|| type == DataType.PRIVATE_IDENTITY
@ -86,9 +86,9 @@ public final class DataElement implements Parcelable {
|| type == DataType.PUBLIC_IDENTITY
|| type == DataType.PROVISIONED_IDENTITY
|| type == DataType.TX_POWER
|| type == DataType.INTENT
|| type == DataType.ACTION
|| type == DataType.MODEL_ID
|| type == DataType.FINDER_EPHEMERAL_IDENTIFIER
|| type == DataType.EDDYSTONE_EPHEMERAL_IDENTIFIER
|| type == DataType.CONNECTION_STATUS
|| type == DataType.BATTERY;
}

View file

@ -54,7 +54,11 @@ import com.android.server.nearby.util.permissions.DiscoveryPermissions;
/** Service implementing nearby functionality. */
public class NearbyService extends INearbyManager.Stub {
public static final String TAG = "NearbyService";
// Sets to true to start BLE scan from PresenceManager for manual testing.
public static final Boolean MANUAL_TEST = false;
// Sets to true to support Mainline Test App.
// This will disable BLE privilege check and legacy broadcast support check.
public static final Boolean SUPPORT_TEST_APP = false;
private final Context mContext;
private Injector mInjector;
@ -187,9 +191,11 @@ public class NearbyService extends INearbyManager.Stub {
*/
@RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
private static void enforceBluetoothPrivilegedPermission(Context context) {
context.enforceCallingOrSelfPermission(
android.Manifest.permission.BLUETOOTH_PRIVILEGED,
"Need BLUETOOTH PRIVILEGED permission");
if (!SUPPORT_TEST_APP) {
context.enforceCallingOrSelfPermission(
android.Manifest.permission.BLUETOOTH_PRIVILEGED,
"Need BLUETOOTH PRIVILEGED permission");
}
}
private static final class SystemInjector implements Injector {

View file

@ -230,7 +230,7 @@ public class ExtendedAdvertisement extends Advertisement{
dataElementArrayIndex += deHeaderArray.length;
@DataElement.DataType int type = Objects.requireNonNull(deHeader).getDataType();
if (type == DataElement.DataType.INTENT) {
if (type == DataElement.DataType.ACTION) {
if (deHeader.getDataLength() != 1) {
Log.v(TAG, "Action id should only 1 byte.");
return null;
@ -321,7 +321,7 @@ public class ExtendedAdvertisement extends Advertisement{
List<Byte> dataElementBytes = new ArrayList<>();
// Intents
for (int action : mActions) {
DataElement actionElement = new DataElement(DataElement.DataType.INTENT,
DataElement actionElement = new DataElement(DataElement.DataType.ACTION,
new byte[] {(byte) action});
byte[] intentByteArray =
ExtendedAdvertisementUtils.convertDataElementToBytes(actionElement);

View file

@ -16,9 +16,10 @@
package com.android.server.nearby.presence;
import static com.android.server.nearby.NearbyService.TAG;
import android.annotation.NonNull;
import android.nearby.DataElement;
import android.nearby.NearbyDevice;
import android.nearby.NearbyDeviceParcelable;
import android.nearby.PresenceDevice;
import android.nearby.PresenceScanFilter;
@ -38,10 +39,22 @@ public class PresenceDiscoveryResult {
/** Creates a {@link PresenceDiscoveryResult} from the scan data. */
public static PresenceDiscoveryResult fromDevice(NearbyDeviceParcelable device) {
PresenceDevice presenceDevice = device.getPresenceDevice();
if (presenceDevice != null) {
return new PresenceDiscoveryResult.Builder()
.setTxPower(device.getTxPower())
.setRssi(device.getRssi())
.setSalt(presenceDevice.getSalt())
.setPublicCredential(device.getPublicCredential())
.addExtendedProperties(presenceDevice.getExtendedProperties())
.setEncryptedIdentityTag(device.getEncryptionKeyTag())
.build();
}
byte[] salt = device.getSalt();
if (salt == null) {
salt = new byte[0];
}
PresenceDiscoveryResult.Builder builder = new PresenceDiscoveryResult.Builder();
builder.setTxPower(device.getTxPower())
.setRssi(device.getRssi())
@ -60,6 +73,7 @@ public class PresenceDiscoveryResult {
private final List<Integer> mPresenceActions;
private final PublicCredential mPublicCredential;
private final List<DataElement> mExtendedProperties;
private final byte[] mEncryptedIdentityTag;
private PresenceDiscoveryResult(
int txPower,
@ -67,13 +81,15 @@ public class PresenceDiscoveryResult {
byte[] salt,
List<Integer> presenceActions,
PublicCredential publicCredential,
List<DataElement> extendedProperties) {
List<DataElement> extendedProperties,
byte[] encryptedIdentityTag) {
mTxPower = txPower;
mRssi = rssi;
mSalt = salt;
mPresenceActions = presenceActions;
mPublicCredential = publicCredential;
mExtendedProperties = extendedProperties;
mEncryptedIdentityTag = encryptedIdentityTag;
}
/** Returns whether the discovery result matches the scan filter. */
@ -81,9 +97,10 @@ public class PresenceDiscoveryResult {
if (accountKeyMatches(scanFilter.getExtendedProperties())) {
return true;
}
return pathLossMatches(scanFilter.getMaxPathLoss())
&& actionMatches(scanFilter.getPresenceActions())
&& credentialMatches(scanFilter.getCredentials());
&& identityMatches(scanFilter.getCredentials());
}
private boolean pathLossMatches(int maxPathLoss) {
@ -97,45 +114,41 @@ public class PresenceDiscoveryResult {
return filterActions.stream().anyMatch(mPresenceActions::contains);
}
private boolean credentialMatches(List<PublicCredential> credentials) {
return credentials.contains(mPublicCredential);
}
@VisibleForTesting
boolean accountKeyMatches(List<DataElement> extendedProperties) {
Set<byte[]> accountKeys = new ArraySet<>();
for (DataElement requestedDe : mExtendedProperties) {
if (requestedDe.getKey() != DataElement.DataType.ACCOUNT_KEY) {
if (requestedDe.getKey() != DataElement.DataType.ACCOUNT_KEY_DATA) {
continue;
}
accountKeys.add(requestedDe.getValue());
}
for (DataElement scannedDe : extendedProperties) {
if (scannedDe.getKey() != DataElement.DataType.ACCOUNT_KEY) {
if (scannedDe.getKey() != DataElement.DataType.ACCOUNT_KEY_DATA) {
continue;
}
// If one account key matches, then returns true.
for (byte[] key : accountKeys) {
if (Arrays.equals(key, scannedDe.getValue())) {
Log.d("NearbyService", "PresenceDiscoveryResult account key matched");
return true;
}
}
}
return false;
}
/** Converts a presence device from the discovery result. */
public PresenceDevice toPresenceDevice() {
return new PresenceDevice.Builder(
// Use the public credential hash as the device Id.
String.valueOf(mPublicCredential.hashCode()),
mSalt,
mPublicCredential.getSecretId(),
mPublicCredential.getEncryptedMetadata())
.setRssi(mRssi)
.addMedium(NearbyDevice.Medium.BLE)
.build();
private boolean identityMatches(List<PublicCredential> publicCredentials) {
if (mEncryptedIdentityTag.length == 0) {
return true;
}
for (PublicCredential publicCredential : publicCredentials) {
if (Arrays.equals(
mEncryptedIdentityTag, publicCredential.getEncryptedMetadataKeyTag())) {
return true;
}
}
return false;
}
/** Builder for {@link PresenceDiscoveryResult}. */
@ -147,6 +160,7 @@ public class PresenceDiscoveryResult {
private PublicCredential mPublicCredential;
private final List<Integer> mPresenceActions;
private final List<DataElement> mExtendedProperties;
private byte[] mEncryptedIdentityTag = new byte[0];
public Builder() {
mPresenceActions = new ArrayList<>();
@ -173,7 +187,18 @@ public class PresenceDiscoveryResult {
/** Sets the public credential for the discovery result. */
public Builder setPublicCredential(PublicCredential publicCredential) {
mPublicCredential = publicCredential;
if (publicCredential != null) {
mPublicCredential = publicCredential;
}
return this;
}
/** Sets the encrypted identity tag for the discovery result. Usually it is passed from
* {@link NearbyDeviceParcelable} and the tag is calculated with authenticity key when
* receiving an advertisement.
*/
public Builder setEncryptedIdentityTag(byte[] encryptedIdentityTag) {
mEncryptedIdentityTag = encryptedIdentityTag;
return this;
}
@ -183,9 +208,26 @@ public class PresenceDiscoveryResult {
return this;
}
/** Adds presence {@link DataElement}s of the discovery result. */
public Builder addExtendedProperties(DataElement dataElement) {
if (dataElement.getKey() == DataElement.DataType.ACTION) {
byte[] value = dataElement.getValue();
if (value.length == 1) {
addPresenceAction(Byte.toUnsignedInt(value[0]));
} else {
Log.e(TAG, "invalid action data element");
}
} else {
mExtendedProperties.add(dataElement);
}
return this;
}
/** Adds presence {@link DataElement}s of the discovery result. */
public Builder addExtendedProperties(@NonNull List<DataElement> dataElements) {
mExtendedProperties.addAll(dataElements);
for (DataElement dataElement : dataElements) {
addExtendedProperties(dataElement);
}
return this;
}
@ -193,7 +235,7 @@ public class PresenceDiscoveryResult {
public PresenceDiscoveryResult build() {
return new PresenceDiscoveryResult(
mTxPower, mRssi, mSalt, mPresenceActions,
mPublicCredential, mExtendedProperties);
mPublicCredential, mExtendedProperties, mEncryptedIdentityTag);
}
}
}

View file

@ -94,7 +94,8 @@ public class PresenceManager {
.addCredential(publicCredential)
.addPresenceAction(1)
.addExtendedProperty(new DataElement(
DataElement.DataType.ACCOUNT_KEY, new byte[16]))
DataElement.DataType.ACCOUNT_KEY_DATA,
new byte[16]))
.build();
ScanRequest scanRequest =
new ScanRequest.Builder()

View file

@ -126,7 +126,7 @@ public class BleDiscoveryProvider extends AbstractDiscoveryProvider {
advertisement.getIdentity())
.addMedium(NearbyDevice.Medium.BLE);
for (int i : advertisement.getActions()) {
builder.addExtendedProperty(new DataElement(DataElement.DataType.INTENT,
builder.addExtendedProperty(new DataElement(DataElement.DataType.ACTION,
new byte[]{(byte) i}));
}
for (DataElement dataElement : advertisement.getDataElements()) {

View file

@ -16,6 +16,8 @@
package com.android.server.nearby.provider;
import static com.android.server.nearby.NearbyService.SUPPORT_TEST_APP;
import android.annotation.Nullable;
import android.content.Context;
import android.nearby.BroadcastCallback;
@ -69,10 +71,12 @@ public class BroadcastProviderManager implements BleBroadcastProvider.BroadcastL
public void startBroadcast(BroadcastRequest broadcastRequest, IBroadcastListener listener) {
synchronized (mLock) {
mExecutor.execute(() -> {
NearbyConfiguration configuration = new NearbyConfiguration();
if (!configuration.isPresenceBroadcastLegacyEnabled()) {
reportBroadcastStatus(listener, BroadcastCallback.STATUS_FAILURE);
return;
if (!SUPPORT_TEST_APP) {
NearbyConfiguration configuration = new NearbyConfiguration();
if (!configuration.isPresenceBroadcastLegacyEnabled()) {
reportBroadcastStatus(listener, BroadcastCallback.STATUS_FAILURE);
return;
}
}
if (broadcastRequest.getType() != BroadcastRequest.BROADCAST_TYPE_NEARBY_PRESENCE) {
reportBroadcastStatus(listener, BroadcastCallback.STATUS_FAILURE);
@ -110,7 +114,7 @@ public class BroadcastProviderManager implements BleBroadcastProvider.BroadcastL
*/
public void stopBroadcast(IBroadcastListener listener) {
synchronized (mLock) {
if (!mNearbyConfiguration.isPresenceBroadcastLegacyEnabled()) {
if (!SUPPORT_TEST_APP && !mNearbyConfiguration.isPresenceBroadcastLegacyEnabled()) {
reportBroadcastStatus(listener, BroadcastCallback.STATUS_FAILURE);
return;
}

View file

@ -125,29 +125,43 @@ public class ChreDiscoveryProvider extends AbstractDiscoveryProvider {
for (ScanFilter scanFilter : mScanFilters) {
PresenceScanFilter presenceScanFilter = (PresenceScanFilter) scanFilter;
Blefilter.BleFilter.Builder filterBuilder = Blefilter.BleFilter.newBuilder();
for (PublicCredential credential : presenceScanFilter.getCredentials()) {
filterBuilder.addCertficate(toProtoPublicCredential(credential));
}
for (DataElement dataElement : presenceScanFilter.getExtendedProperties()) {
if (dataElement.getKey() == DataElement.DataType.ACCOUNT_KEY) {
Blefilter.DataElement filterDe =
Blefilter.DataElement.newBuilder()
.setKey(
Blefilter.DataElement.ElementType
.DE_FAST_PAIR_ACCOUNT_KEY)
.setValue(ByteString.copyFrom(dataElement.getValue()))
.setValueLength(FP_ACCOUNT_KEY_LENGTH)
.build();
filterBuilder.addDataElement(filterDe);
if (dataElement.getKey() == DataElement.DataType.ACCOUNT_KEY_DATA) {
filterBuilder.addDataElement(toProtoDataElement(dataElement));
}
}
Log.i(TAG, "add filter");
if (!presenceScanFilter.getPresenceActions().isEmpty()) {
filterBuilder.setIntent(presenceScanFilter.getPresenceActions().get(0));
}
filtersBuilder.addFilter(filterBuilder.build());
}
mFilters = filtersBuilder.build();
if (mChreStarted) {
sendFilters(mFilters);
sendFilters(filtersBuilder.build());
mFilters = null;
}
}
private Blefilter.PublicateCertificate toProtoPublicCredential(PublicCredential credential) {
return Blefilter.PublicateCertificate.newBuilder()
.setAuthenticityKey(ByteString.copyFrom(credential.getAuthenticityKey()))
.setMetadataEncryptionKeyTag(
ByteString.copyFrom(credential.getEncryptedMetadataKeyTag()))
.build();
}
private Blefilter.DataElement toProtoDataElement(DataElement dataElement) {
return Blefilter.DataElement.newBuilder()
.setKey(
Blefilter.DataElement.ElementType
.DE_FAST_PAIR_ACCOUNT_KEY)
.setValue(ByteString.copyFrom(dataElement.getValue()))
.setValueLength(FP_ACCOUNT_KEY_LENGTH)
.build();
}
private void sendFilters(Blefilter.BleFilters filters) {
NanoAppMessage message =
NanoAppMessage.createMessageToNanoApp(
@ -242,7 +256,7 @@ public class ChreDiscoveryProvider extends AbstractDiscoveryProvider {
== Blefilter.DataElement.ElementType.DE_FAST_PAIR_ACCOUNT_KEY) {
presenceDeviceBuilder.addExtendedProperty(
new DataElement(
DataElement.DataType.ACCOUNT_KEY,
DataElement.DataType.ACCOUNT_KEY_DATA,
element.getValue().toByteArray()));
}
}
@ -261,6 +275,14 @@ public class ChreDiscoveryProvider extends AbstractDiscoveryProvider {
filterResult.getBleServiceData().toByteArray()));
}
// Add action
if (filterResult.hasIntent()) {
presenceDeviceBuilder.addExtendedProperty(
new DataElement(
DataElement.DataType.ACTION,
new byte[]{(byte) filterResult.getIntent()}));
}
PublicCredential publicCredential =
new PublicCredential.Builder(
secretId,
@ -276,9 +298,10 @@ public class ChreDiscoveryProvider extends AbstractDiscoveryProvider {
.setMedium(NearbyDevice.Medium.BLE)
.setTxPower(filterResult.getTxPower())
.setRssi(filterResult.getRssi())
.setAction(0)
.setAction(filterResult.getIntent())
.setPublicCredential(publicCredential)
.setPresenceDevice(presenceDeviceBuilder.build())
.setEncryptionKeyTag(encryptedMetaDataTag)
.build();
mExecutor.execute(() -> mListener.onNearbyDeviceDiscovered(device));
}

View file

@ -92,10 +92,9 @@ public class DiscoveryProviderManager implements AbstractDiscoveryProvider.Liste
scanFilter.getType()
== SCAN_TYPE_NEARBY_PRESENCE)
.collect(Collectors.toList());
Log.i(
TAG,
String.format("match with filters size: %d", presenceFilters.size()));
if (!presenceFilterMatches(nearbyDevice, presenceFilters)) {
Log.d(TAG, "presence filter does not match for "
+ "the scanned Presence Device");
continue;
}
}

View file

@ -38,9 +38,9 @@ import java.util.List;
public class ExtendedAdvertisementTest {
private static final int IDENTITY_TYPE = PresenceCredential.IDENTITY_TYPE_PRIVATE;
private static final int DATA_TYPE_MODEL_ID = 10;
private static final int DATA_TYPE_BLE_ADDRESS = 2;
private static final int DATA_TYPE_PUBLIC_IDENTITY = 6;
private static final int DATA_TYPE_MODEL_ID = 7;
private static final int DATA_TYPE_BLE_ADDRESS = 101;
private static final int DATA_TYPE_PUBLIC_IDENTITY = 3;
private static final byte[] MODE_ID_DATA =
new byte[]{2, 1, 30, 2, 10, -16, 6, 22, 44, -2, -86, -69, -52};
private static final byte[] BLE_ADDRESS = new byte[]{124, 4, 56, 60, 120, -29, -90};
@ -114,7 +114,7 @@ public class ExtendedAdvertisementTest {
.containsExactly(PRESENCE_ACTION_1, PRESENCE_ACTION_2);
assertThat(originalAdvertisement.getIdentity()).isEqualTo(IDENTITY);
assertThat(originalAdvertisement.getIdentityType()).isEqualTo(IDENTITY_TYPE);
assertThat(originalAdvertisement.getLength()).isEqualTo(65);
assertThat(originalAdvertisement.getLength()).isEqualTo(66);
assertThat(originalAdvertisement.getVersion()).isEqualTo(
BroadcastRequest.PRESENCE_VERSION_V1);
assertThat(originalAdvertisement.getSalt()).isEqualTo(SALT);
@ -136,7 +136,7 @@ public class ExtendedAdvertisementTest {
.containsExactly(PRESENCE_ACTION_1, PRESENCE_ACTION_2);
assertThat(newAdvertisement.getIdentity()).isEqualTo(IDENTITY);
assertThat(newAdvertisement.getIdentityType()).isEqualTo(IDENTITY_TYPE);
assertThat(newAdvertisement.getLength()).isEqualTo(65);
assertThat(newAdvertisement.getLength()).isEqualTo(66);
assertThat(newAdvertisement.getVersion()).isEqualTo(
BroadcastRequest.PRESENCE_VERSION_V1);
assertThat(newAdvertisement.getSalt()).isEqualTo(SALT);
@ -195,7 +195,7 @@ public class ExtendedAdvertisementTest {
.containsExactly(PRESENCE_ACTION_1, PRESENCE_ACTION_2);
assertThat(adv.getIdentity()).isEqualTo(IDENTITY);
assertThat(adv.getIdentityType()).isEqualTo(IDENTITY_TYPE);
assertThat(adv.getLength()).isEqualTo(65);
assertThat(adv.getLength()).isEqualTo(66);
assertThat(adv.getVersion()).isEqualTo(
BroadcastRequest.PRESENCE_VERSION_V1);
assertThat(adv.getSalt()).isEqualTo(SALT);
@ -207,7 +207,7 @@ public class ExtendedAdvertisementTest {
public void test_toString() {
ExtendedAdvertisement adv = ExtendedAdvertisement.createFromRequest(mBuilder.build());
assertThat(adv.toString()).isEqualTo("ExtendedAdvertisement:"
+ "<VERSION: 1, length: 65, dataElementCount: 2, identityType: 1, "
+ "<VERSION: 1, length: 66, dataElementCount: 2, identityType: 1, "
+ "identity: [1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4], salt: [2, 3],"
+ " actions: [1, 2]>");
}
@ -223,31 +223,31 @@ public class ExtendedAdvertisementTest {
}
private static byte[] getExtendedAdvertisementByteArray() {
ByteBuffer buffer = ByteBuffer.allocate(65);
ByteBuffer buffer = ByteBuffer.allocate(66);
buffer.put((byte) 0b00100000); // Header V1
buffer.put((byte) 0b00100011); // Salt header: length 2, type 3
buffer.put((byte) 0b00100000); // Salt header: length 2, type 0
// Salt data
buffer.put(SALT);
// Identity header: length 16, type 4
buffer.put(new byte[]{(byte) 0b10010000, (byte) 0b00000100});
// Identity header: length 16, type 1 (private identity)
buffer.put(new byte[]{(byte) 0b10010000, (byte) 0b00000001});
// Identity data
buffer.put(CryptorImpIdentityV1.getInstance().encrypt(IDENTITY, SALT, AUTHENTICITY_KEY));
ByteBuffer deBuffer = ByteBuffer.allocate(27);
// Action1 header: length 1, type 9
deBuffer.put(new byte[]{(byte) 0b00011001});
ByteBuffer deBuffer = ByteBuffer.allocate(28);
// Action1 header: length 1, type 6
deBuffer.put(new byte[]{(byte) 0b00010110});
// Action1 data
deBuffer.put((byte) PRESENCE_ACTION_1);
// Action2 header: length 1, type 9
deBuffer.put(new byte[]{(byte) 0b00011001});
// Action2 header: length 1, type 6
deBuffer.put(new byte[]{(byte) 0b00010110});
// Action2 data
deBuffer.put((byte) PRESENCE_ACTION_2);
// Ble address header: length 7, type 2
deBuffer.put((byte) 0b01110010);
// Ble address header: length 7, type 102
deBuffer.put(new byte[]{(byte) 0b10000111, (byte) 0b01100101});
// Ble address data
deBuffer.put(BLE_ADDRESS);
// model id header: length 13, type 10
deBuffer.put(new byte[]{(byte) 0b10001101, (byte) 0b00001010});
// model id header: length 13, type 7
deBuffer.put(new byte[]{(byte) 0b10001101, (byte) 0b00000111});
// model id data
deBuffer.put(MODE_ID_DATA);

View file

@ -31,15 +31,14 @@ import org.junit.Before;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* Unit tests for {@link PresenceDiscoveryResult}.
*/
public class PresenceDiscoveryResultTest {
private static final int DATA_TYPE_ACCOUNT_KEY = 1;
private static final int DATA_TYPE_INTENT = 9;
private static final int DATA_TYPE_ACCOUNT_KEY = 9;
private static final int DATA_TYPE_INTENT = 6;
private static final int PRESENCE_ACTION = 123;
private static final int TX_POWER = -1;
private static final int RSSI = -41;
@ -49,6 +48,8 @@ public class PresenceDiscoveryResultTest {
private static final byte[] PUBLIC_KEY = new byte[]{1, 1, 2, 2};
private static final byte[] ENCRYPTED_METADATA = new byte[]{1, 2, 3, 4, 5};
private static final byte[] METADATA_ENCRYPTION_KEY_TAG = new byte[]{1, 1, 3, 4, 5};
private static final byte[] META_DATA_ENCRYPTION_KEY =
new byte[] {-39, -55, 115, 78, -57, 40, 115, 0, -112, 86, -86, 7, -42, 68, 11, 12};
private PresenceDiscoveryResult.Builder mBuilder;
private PublicCredential mCredential;
@ -65,6 +66,7 @@ public class PresenceDiscoveryResultTest {
.setSalt(SALT)
.setTxPower(TX_POWER)
.setRssi(RSSI)
.setEncryptedIdentityTag(METADATA_ENCRYPTION_KEY_TAG)
.addPresenceAction(PRESENCE_ACTION);
}
@ -90,13 +92,28 @@ public class PresenceDiscoveryResultTest {
@Test
@SdkSuppress(minSdkVersion = 32, codeName = "T")
public void testToDevice() {
PresenceDiscoveryResult discoveryResult = mBuilder.build();
PresenceDevice presenceDevice = discoveryResult.toPresenceDevice();
public void testFromDevice_presenceDeviceAvailable() {
NearbyDeviceParcelable.Builder builder = new NearbyDeviceParcelable.Builder();
PresenceDevice presenceDevice =
new PresenceDevice.Builder("123", SALT, SECRET_ID, META_DATA_ENCRYPTION_KEY)
.addExtendedProperty(new DataElement(
DATA_TYPE_INTENT, new byte[]{(byte) PRESENCE_ACTION}))
.build();
builder.setTxPower(TX_POWER)
.setRssi(RSSI)
.setEncryptionKeyTag(METADATA_ENCRYPTION_KEY_TAG)
.setPresenceDevice(presenceDevice)
.setPublicCredential(mCredential);
assertThat(presenceDevice.getRssi()).isEqualTo(RSSI);
assertThat(Arrays.equals(presenceDevice.getSalt(), SALT)).isTrue();
assertThat(Arrays.equals(presenceDevice.getSecretId(), SECRET_ID)).isTrue();
PresenceDiscoveryResult discoveryResult =
PresenceDiscoveryResult.fromDevice(builder.build());
PresenceScanFilter scanFilter = new PresenceScanFilter.Builder()
.setMaxPathLoss(80)
.addPresenceAction(PRESENCE_ACTION)
.addCredential(mCredential)
.build();
assertThat(discoveryResult.matches(scanFilter)).isTrue();
}
@Test
@ -126,4 +143,24 @@ public class PresenceDiscoveryResultTest {
assertThat(discoveryResult.matches(scanFilter)).isTrue();
}
@Test
@SdkSuppress(minSdkVersion = 32, codeName = "T")
public void test_notMatches() {
PresenceDiscoveryResult.Builder builder = new PresenceDiscoveryResult.Builder()
.setPublicCredential(mCredential)
.setSalt(SALT)
.setTxPower(TX_POWER)
.setRssi(RSSI)
.setEncryptedIdentityTag(new byte[]{5, 4, 3, 2, 1})
.addPresenceAction(PRESENCE_ACTION);
PresenceScanFilter scanFilter = new PresenceScanFilter.Builder()
.setMaxPathLoss(80)
.addPresenceAction(PRESENCE_ACTION)
.addCredential(mCredential)
.build();
PresenceDiscoveryResult discoveryResult = builder.build();
assertThat(discoveryResult.matches(scanFilter)).isFalse();
}
}