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:
commit
c43c69bbb6
11 changed files with 215 additions and 103 deletions
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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()) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue