Allows Test Data Elements with Filter

Bug: 259299293
Test: atest NearbyUnitTests and on device test
Ignore-AOSP-First: nearby_not_in_aosp_yet
Change-Id: I2d0a537d38ac7b602bc49dcf2113c43f1b654cb2
This commit is contained in:
Jayden Kim 2023-01-14 15:51:44 +00:00
commit 99ba7e5fb3
4 changed files with 281 additions and 25 deletions

View file

@ -55,7 +55,9 @@ public final class DataElement implements Parcelable {
DataType.ACCOUNT_KEY_DATA,
DataType.CONNECTION_STATUS,
DataType.BATTERY,
DataType.SCAN_MODE
DataType.SCAN_MODE,
DataType.TEST_DE_BEGIN,
DataType.TEST_DE_END
})
public @interface DataType {
int BLE_SERVICE_DATA = 100;
@ -74,6 +76,10 @@ public final class DataElement implements Parcelable {
int ACCOUNT_KEY_DATA = 9;
int CONNECTION_STATUS = 10;
int BATTERY = 11;
// Reserves test DE ranges from {@link DataElement.DataType#TEST_DE_BEGIN}
// to {@link DataElement.DataType#TEST_DE_END}, inclusive.
int TEST_DE_BEGIN = 256;
int TEST_DE_END = 260;
}
/**
@ -108,6 +114,14 @@ public final class DataElement implements Parcelable {
|| mKey == DataType.PROVISIONED_IDENTITY;
}
/**
* @return {@code true} if this is test data element type.
* @hide
*/
public static boolean isTestDeType(int type) {
return type >= DataType.TEST_DE_BEGIN && type <= DataType.TEST_DE_END;
}
/**
* Constructs a {@link DataElement}.
*/

View file

@ -20,10 +20,6 @@ import static android.nearby.ScanRequest.SCAN_TYPE_NEARBY_PRESENCE;
import static com.android.server.nearby.NearbyService.TAG;
import static service.proto.Blefilter.DataElement.ElementType.DE_BATTERY_STATUS;
import static service.proto.Blefilter.DataElement.ElementType.DE_CONNECTION_STATUS;
import static service.proto.Blefilter.DataElement.ElementType.DE_FAST_PAIR_ACCOUNT_KEY;
import android.annotation.Nullable;
import android.content.BroadcastReceiver;
import android.content.Context;
@ -40,9 +36,11 @@ import android.nearby.ScanFilter;
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.nearby.NearbyConfiguration;
import com.google.protobuf.ByteString;
import java.util.Arrays;
import java.util.Collections;
import java.util.concurrent.Executor;
@ -52,13 +50,17 @@ import service.proto.Blefilter;
public class ChreDiscoveryProvider extends AbstractDiscoveryProvider {
// Nanoapp ID reserved for Nearby Presence.
/** @hide */
@VisibleForTesting public static final long NANOAPP_ID = 0x476f6f676c001031L;
@VisibleForTesting
public static final long NANOAPP_ID = 0x476f6f676c001031L;
/** @hide */
@VisibleForTesting public static final int NANOAPP_MESSAGE_TYPE_FILTER = 3;
@VisibleForTesting
public static final int NANOAPP_MESSAGE_TYPE_FILTER = 3;
/** @hide */
@VisibleForTesting public static final int NANOAPP_MESSAGE_TYPE_FILTER_RESULT = 4;
@VisibleForTesting
public static final int NANOAPP_MESSAGE_TYPE_FILTER_RESULT = 4;
/** @hide */
@VisibleForTesting public static final int NANOAPP_MESSAGE_TYPE_CONFIG = 5;
@VisibleForTesting
public static final int NANOAPP_MESSAGE_TYPE_CONFIG = 5;
private static final int FP_ACCOUNT_KEY_LENGTH = 16;
@ -67,6 +69,7 @@ public class ChreDiscoveryProvider extends AbstractDiscoveryProvider {
private boolean mChreStarted = false;
private Blefilter.BleFilters mFilters = null;
private Context mContext;
private NearbyConfiguration mNearbyConfiguration;
private final IntentFilter mIntentFilter;
private final BroadcastReceiver mScreenBroadcastReceiver =
@ -93,6 +96,7 @@ public class ChreDiscoveryProvider extends AbstractDiscoveryProvider {
/** Initialize the CHRE discovery provider. */
public void init() {
mChreCommunication.start(mChreCallback, Collections.singleton(NANOAPP_ID));
mNearbyConfiguration = new NearbyConfiguration();
}
@Override
@ -138,6 +142,9 @@ public class ChreDiscoveryProvider extends AbstractDiscoveryProvider {
for (DataElement dataElement : presenceScanFilter.getExtendedProperties()) {
if (dataElement.getKey() == DataElement.DataType.ACCOUNT_KEY_DATA) {
filterBuilder.addDataElement(toProtoDataElement(dataElement));
} else if (mNearbyConfiguration.isTestAppSupported()
&& DataElement.isTestDeType(dataElement.getKey())) {
filterBuilder.addDataElement(toProtoDataElement(dataElement));
}
}
if (!presenceScanFilter.getPresenceActions().isEmpty()) {
@ -153,7 +160,8 @@ public class ChreDiscoveryProvider extends AbstractDiscoveryProvider {
private Blefilter.PublicateCertificate toProtoPublicCredential(PublicCredential credential) {
Log.d(TAG, String.format("Returns a PublicCertificate with authenticity key size %d and"
+ " encrypted metadata key tag size %d", credential.getAuthenticityKey().length,
+ " encrypted metadata key tag size %d",
credential.getAuthenticityKey().length,
credential.getEncryptedMetadataKeyTag().length));
return Blefilter.PublicateCertificate.newBuilder()
.setAuthenticityKey(ByteString.copyFrom(credential.getAuthenticityKey()))
@ -164,12 +172,13 @@ public class ChreDiscoveryProvider extends AbstractDiscoveryProvider {
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();
.setKey(Arrays.stream(Blefilter.DataElement.ElementType.values())
.filter(p -> p.getNumber() == dataElement.getKey())
.findFirst()
.get())
.setValue(ByteString.copyFrom(dataElement.getValue()))
.setValueLength(dataElement.getValue().length)
.build();
}
private void sendFilters(Blefilter.BleFilters filters) {
@ -258,10 +267,10 @@ public class ChreDiscoveryProvider extends AbstractDiscoveryProvider {
}
PresenceDevice.Builder presenceDeviceBuilder =
new PresenceDevice.Builder(
String.valueOf(filterResult.hashCode()),
salt,
secretId,
encryptedMetaData)
String.valueOf(filterResult.hashCode()),
salt,
secretId,
encryptedMetaData)
.setRssi(filterResult.getRssi())
.addMedium(NearbyDevice.Medium.BLE);
// Data Elements reported from nanoapp added to Data Elements.
@ -306,11 +315,11 @@ public class ChreDiscoveryProvider extends AbstractDiscoveryProvider {
PublicCredential publicCredential =
new PublicCredential.Builder(
secretId,
authenticityKey,
publicKey,
encryptedMetaData,
encryptedMetaDataTag)
secretId,
authenticityKey,
publicKey,
encryptedMetaData,
encryptedMetaDataTag)
.build();
NearbyDeviceParcelable device =
@ -353,6 +362,16 @@ public class ChreDiscoveryProvider extends AbstractDiscoveryProvider {
element.getValue().substring(0, endIndex).toByteArray()));
break;
default:
if (mNearbyConfiguration.isTestAppSupported()
&& DataElement.isTestDeType(element.getKey().getNumber())) {
presenceDeviceBuilder.addExtendedProperty(
new DataElement(Arrays.stream(
Blefilter.DataElement.ElementType.values())
.filter(p -> p.getNumber() == element.getKey().getNumber())
.findFirst()
.get().getNumber(),
element.getValue().substring(0, endIndex).toByteArray()));
}
break;
}
}

View file

@ -58,10 +58,20 @@ message PublicCredential {
message DataElement {
enum ElementType {
option allow_alias = true;
DE_NONE = 0;
DE_FAST_PAIR_ACCOUNT_KEY = 9;
DE_CONNECTION_STATUS = 10;
DE_BATTERY_STATUS = 11;
// Reserves Test DEs.
DE_TEST_BEGIN = 256;
DE_TEST_1 = 256;
DE_TEST_2 = 257;
DE_TEST_3 = 258;
DE_TEST_4 = 259;
DE_TEST_5 = 260;
DE_TEST_END = 260;
}
optional ElementType key = 1;

View file

@ -16,6 +16,12 @@
package com.android.server.nearby.provider;
import static android.Manifest.permission.READ_DEVICE_CONFIG;
import static android.Manifest.permission.WRITE_DEVICE_CONFIG;
import static android.provider.DeviceConfig.NAMESPACE_TETHERING;
import static com.android.server.nearby.NearbyConfiguration.NEARBY_SUPPORT_TEST_APP;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
@ -25,10 +31,12 @@ import android.content.Context;
import android.hardware.location.NanoAppMessage;
import android.nearby.DataElement;
import android.nearby.NearbyDeviceParcelable;
import android.provider.DeviceConfig;
import androidx.test.filters.SdkSuppress;
import androidx.test.platform.app.InstrumentationRegistry;
import com.android.server.nearby.NearbyConfiguration;
import com.android.server.nearby.presence.PresenceDiscoveryResult;
import com.google.protobuf.ByteString;
@ -59,11 +67,20 @@ public class ChreDiscoveryProviderTest {
private static final int DATA_TYPE_BLUETOOTH_ADDR_KEY = 101;
private static final int DATA_TYPE_FP_ACCOUNT_KEY = 9;
private static final int DATA_TYPE_BLE_SERVICE_DATA_KEY = 100;
private static final int DATA_TYPE_TEST_1_KEY = 256;
private static final int DATA_TYPE_TEST_2_KEY = 257;
private static final int DATA_TYPE_TEST_3_KEY = 258;
private static final int DATA_TYPE_TEST_4_KEY = 259;
private static final int DATA_TYPE_TEST_5_KEY = 260;
private ChreDiscoveryProvider mChreDiscoveryProvider;
@Before
public void setUp() {
InstrumentationRegistry.getInstrumentation().getUiAutomation()
.adoptShellPermissionIdentity(WRITE_DEVICE_CONFIG, READ_DEVICE_CONFIG);
MockitoAnnotations.initMocks(this);
Context context = InstrumentationRegistry.getInstrumentation().getContext();
mChreDiscoveryProvider =
@ -113,6 +130,14 @@ public class ChreDiscoveryProviderTest {
@Test
@SdkSuppress(minSdkVersion = 32, codeName = "T")
public void testOnNearbyDeviceDiscoveredWithDataElements() {
// Disables the setting of test app support
boolean isSupportedTestApp = getDeviceConfigBoolean(
NEARBY_SUPPORT_TEST_APP, false /* defaultValue */);
if (isSupportedTestApp) {
DeviceConfig.setProperty(NAMESPACE_TETHERING, NEARBY_SUPPORT_TEST_APP, "false", false);
}
assertThat(new NearbyConfiguration().isTestAppSupported()).isFalse();
final byte [] connectionStatus = new byte[] {1, 2, 3};
final byte [] batteryStatus = new byte[] {4, 5, 6};
final byte [] txPower = new byte[] {2};
@ -120,6 +145,7 @@ public class ChreDiscoveryProviderTest {
final byte [] fastPairAccountKey = new byte[16];
// First byte is length of service data, padding zeros should be thrown away.
final byte [] bleServiceData = new byte[] {5, 1, 2, 3, 4, 5, 0, 0, 0, 0};
final byte [] testData = new byte[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
final List<DataElement> expectedExtendedProperties = new ArrayList<>();
expectedExtendedProperties.add(new DataElement(DATA_TYPE_CONNECTION_STATUS_KEY,
@ -169,6 +195,41 @@ public class ChreDiscoveryProviderTest {
.setValue(ByteString.copyFrom(fastPairAccountKey))
.setValueLength(fastPairAccountKey.length)
)
.addDataElement(Blefilter.DataElement.newBuilder()
.setKey(
Blefilter.DataElement.ElementType
.DE_TEST_1)
.setValue(ByteString.copyFrom(testData))
.setValueLength(testData.length)
)
.addDataElement(Blefilter.DataElement.newBuilder()
.setKey(
Blefilter.DataElement.ElementType
.DE_TEST_2)
.setValue(ByteString.copyFrom(testData))
.setValueLength(testData.length)
)
.addDataElement(Blefilter.DataElement.newBuilder()
.setKey(
Blefilter.DataElement.ElementType
.DE_TEST_3)
.setValue(ByteString.copyFrom(testData))
.setValueLength(testData.length)
)
.addDataElement(Blefilter.DataElement.newBuilder()
.setKey(
Blefilter.DataElement.ElementType
.DE_TEST_4)
.setValue(ByteString.copyFrom(testData))
.setValueLength(testData.length)
)
.addDataElement(Blefilter.DataElement.newBuilder()
.setKey(
Blefilter.DataElement.ElementType
.DE_TEST_5)
.setValue(ByteString.copyFrom(testData))
.setValueLength(testData.length)
)
.build();
Blefilter.BleFilterResults results =
Blefilter.BleFilterResults.newBuilder().addResult(result).build();
@ -187,6 +248,158 @@ public class ChreDiscoveryProviderTest {
List<DataElement> extendedProperties = PresenceDiscoveryResult
.fromDevice(mNearbyDevice.getValue()).getExtendedProperties();
assertThat(extendedProperties).containsExactlyElementsIn(expectedExtendedProperties);
// Reverts the setting of test app support
if (isSupportedTestApp) {
DeviceConfig.setProperty(NAMESPACE_TETHERING, NEARBY_SUPPORT_TEST_APP, "true", false);
assertThat(new NearbyConfiguration().isTestAppSupported()).isTrue();
}
}
@Test
@SdkSuppress(minSdkVersion = 32, codeName = "T")
public void testOnNearbyDeviceDiscoveredWithTestDataElements() {
// Enables the setting of test app support
boolean isSupportedTestApp = getDeviceConfigBoolean(
NEARBY_SUPPORT_TEST_APP, false /* defaultValue */);
if (!isSupportedTestApp) {
DeviceConfig.setProperty(NAMESPACE_TETHERING, NEARBY_SUPPORT_TEST_APP, "true", false);
}
assertThat(new NearbyConfiguration().isTestAppSupported()).isTrue();
final byte [] connectionStatus = new byte[] {1, 2, 3};
final byte [] batteryStatus = new byte[] {4, 5, 6};
final byte [] txPower = new byte[] {2};
final byte [] bluetoothAddr = new byte[] {1, 2, 3, 4, 5, 6};
final byte [] fastPairAccountKey = new byte[16];
// First byte is length of service data, padding zeros should be thrown away.
final byte [] bleServiceData = new byte[] {5, 1, 2, 3, 4, 5, 0, 0, 0, 0};
final byte [] testData = new byte[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
final List<DataElement> expectedExtendedProperties = new ArrayList<>();
expectedExtendedProperties.add(new DataElement(DATA_TYPE_CONNECTION_STATUS_KEY,
connectionStatus));
expectedExtendedProperties.add(new DataElement(DATA_TYPE_BATTERY_KEY, batteryStatus));
expectedExtendedProperties.add(new DataElement(DATA_TYPE_TX_POWER_KEY, txPower));
expectedExtendedProperties.add(
new DataElement(DATA_TYPE_BLUETOOTH_ADDR_KEY, bluetoothAddr));
expectedExtendedProperties.add(
new DataElement(DATA_TYPE_FP_ACCOUNT_KEY, fastPairAccountKey));
expectedExtendedProperties.add(
new DataElement(DATA_TYPE_BLE_SERVICE_DATA_KEY, new byte[] {1, 2, 3, 4, 5}));
expectedExtendedProperties.add(
new DataElement(DATA_TYPE_TEST_1_KEY, testData));
expectedExtendedProperties.add(
new DataElement(DATA_TYPE_TEST_2_KEY, testData));
expectedExtendedProperties.add(
new DataElement(DATA_TYPE_TEST_3_KEY, testData));
expectedExtendedProperties.add(
new DataElement(DATA_TYPE_TEST_4_KEY, testData));
expectedExtendedProperties.add(
new DataElement(DATA_TYPE_TEST_5_KEY, testData));
Blefilter.PublicCredential credential =
Blefilter.PublicCredential.newBuilder()
.setSecretId(ByteString.copyFrom(new byte[] {1}))
.setAuthenticityKey(ByteString.copyFrom(new byte[2]))
.setPublicKey(ByteString.copyFrom(new byte[3]))
.setEncryptedMetadata(ByteString.copyFrom(new byte[4]))
.setEncryptedMetadataTag(ByteString.copyFrom(new byte[5]))
.build();
Blefilter.BleFilterResult result =
Blefilter.BleFilterResult.newBuilder()
.setTxPower(2)
.setRssi(1)
.setBluetoothAddress(ByteString.copyFrom(bluetoothAddr))
.setBleServiceData(ByteString.copyFrom(bleServiceData))
.setPublicCredential(credential)
.addDataElement(Blefilter.DataElement.newBuilder()
.setKey(
Blefilter.DataElement.ElementType
.DE_CONNECTION_STATUS)
.setValue(ByteString.copyFrom(connectionStatus))
.setValueLength(connectionStatus.length)
)
.addDataElement(Blefilter.DataElement.newBuilder()
.setKey(
Blefilter.DataElement.ElementType
.DE_BATTERY_STATUS)
.setValue(ByteString.copyFrom(batteryStatus))
.setValueLength(batteryStatus.length)
)
.addDataElement(Blefilter.DataElement.newBuilder()
.setKey(
Blefilter.DataElement.ElementType
.DE_FAST_PAIR_ACCOUNT_KEY)
.setValue(ByteString.copyFrom(fastPairAccountKey))
.setValueLength(fastPairAccountKey.length)
)
.addDataElement(Blefilter.DataElement.newBuilder()
.setKey(
Blefilter.DataElement.ElementType
.DE_TEST_1)
.setValue(ByteString.copyFrom(testData))
.setValueLength(testData.length)
)
.addDataElement(Blefilter.DataElement.newBuilder()
.setKey(
Blefilter.DataElement.ElementType
.DE_TEST_2)
.setValue(ByteString.copyFrom(testData))
.setValueLength(testData.length)
)
.addDataElement(Blefilter.DataElement.newBuilder()
.setKey(
Blefilter.DataElement.ElementType
.DE_TEST_3)
.setValue(ByteString.copyFrom(testData))
.setValueLength(testData.length)
)
.addDataElement(Blefilter.DataElement.newBuilder()
.setKey(
Blefilter.DataElement.ElementType
.DE_TEST_4)
.setValue(ByteString.copyFrom(testData))
.setValueLength(testData.length)
)
.addDataElement(Blefilter.DataElement.newBuilder()
.setKey(
Blefilter.DataElement.ElementType
.DE_TEST_5)
.setValue(ByteString.copyFrom(testData))
.setValueLength(testData.length)
)
.build();
Blefilter.BleFilterResults results =
Blefilter.BleFilterResults.newBuilder().addResult(result).build();
NanoAppMessage chre_message =
NanoAppMessage.createMessageToNanoApp(
ChreDiscoveryProvider.NANOAPP_ID,
ChreDiscoveryProvider.NANOAPP_MESSAGE_TYPE_FILTER_RESULT,
results.toByteArray());
mChreDiscoveryProvider.getController().setListener(mListener);
mChreDiscoveryProvider.init();
mChreDiscoveryProvider.onStart();
verify(mChreCommunication).start(mChreCallbackCaptor.capture(), any());
mChreCallbackCaptor.getValue().onMessageFromNanoApp(chre_message);
verify(mListener).onNearbyDeviceDiscovered(mNearbyDevice.capture());
List<DataElement> extendedProperties = PresenceDiscoveryResult
.fromDevice(mNearbyDevice.getValue()).getExtendedProperties();
assertThat(extendedProperties).containsExactlyElementsIn(expectedExtendedProperties);
// Reverts the setting of test app support
if (!isSupportedTestApp) {
DeviceConfig.setProperty(NAMESPACE_TETHERING, NEARBY_SUPPORT_TEST_APP, "false", false);
assertThat(new NearbyConfiguration().isTestAppSupported()).isFalse();
}
}
private boolean getDeviceConfigBoolean(final String name, final boolean defaultValue) {
final String value = getDeviceConfigProperty(name);
return value != null ? Boolean.parseBoolean(value) : defaultValue;
}
private String getDeviceConfigProperty(String name) {
return DeviceConfig.getProperty(DeviceConfig.NAMESPACE_TETHERING, name);
}
private static class InLineExecutor implements Executor {