Merge "Fix Gson serialization escaping HTML characters issue and lint problems." into tm-dev
diff --git a/nearby/framework/java/android/nearby/CredentialElement.java b/nearby/framework/java/android/nearby/CredentialElement.java
index d2049d1..7a43b01 100644
--- a/nearby/framework/java/android/nearby/CredentialElement.java
+++ b/nearby/framework/java/android/nearby/CredentialElement.java
@@ -17,12 +17,16 @@
package android.nearby;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
import com.android.internal.util.Preconditions;
+import java.util.Arrays;
+import java.util.Objects;
+
/**
* Represents an element in {@link PresenceCredential}.
*
@@ -33,12 +37,9 @@
private final String mKey;
private final byte[] mValue;
- /**
- * Constructs a {@link CredentialElement}.
- */
+ /** Constructs a {@link CredentialElement}. */
public CredentialElement(@NonNull String key, @NonNull byte[] value) {
- Preconditions.checkState(key != null && value != null,
- "neither key or value can be null");
+ Preconditions.checkState(key != null && value != null, "neither key or value can be null");
mKey = key;
mValue = value;
}
@@ -58,7 +59,7 @@
public CredentialElement[] newArray(int size) {
return new CredentialElement[size];
}
- };
+ };
@Override
public int describeContents() {
@@ -72,19 +73,29 @@
dest.writeByteArray(mValue);
}
- /**
- * Returns the key of the credential element.
- */
+ /** Returns the key of the credential element. */
@NonNull
public String getKey() {
return mKey;
}
- /**
- * Returns the value of the credential element.
- */
+ /** Returns the value of the credential element. */
@NonNull
public byte[] getValue() {
return mValue;
}
+
+ @Override
+ public boolean equals(@Nullable Object obj) {
+ if (obj instanceof CredentialElement) {
+ CredentialElement that = (CredentialElement) obj;
+ return mKey.equals(that.mKey) && Arrays.equals(mValue, that.mValue);
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mKey.hashCode(), Arrays.hashCode(mValue));
+ }
}
diff --git a/nearby/framework/java/android/nearby/NearbyDeviceParcelable.java b/nearby/framework/java/android/nearby/NearbyDeviceParcelable.java
index 694e15b..1ad3571 100644
--- a/nearby/framework/java/android/nearby/NearbyDeviceParcelable.java
+++ b/nearby/framework/java/android/nearby/NearbyDeviceParcelable.java
@@ -29,21 +29,18 @@
/**
* A data class representing scan result from Nearby Service. Scan result can come from multiple
- * mediums like BLE, Wi-Fi Aware, and etc.
- * A scan result consists of
- * An encapsulation of various parameters for requesting nearby scans.
+ * mediums like BLE, Wi-Fi Aware, and etc. A scan result consists of An encapsulation of various
+ * parameters for requesting nearby scans.
*
* <p>All scan results generated through {@link NearbyManager} are guaranteed to have a valid
- * medium, identifier, timestamp (both UTC time and elapsed real-time since boot), and accuracy.
- * All other parameters are optional.
+ * medium, identifier, timestamp (both UTC time and elapsed real-time since boot), and accuracy. All
+ * other parameters are optional.
*
* @hide
*/
public final class NearbyDeviceParcelable implements Parcelable {
- /**
- * Used to read a NearbyDeviceParcelable from a Parcel.
- */
+ /** Used to read a NearbyDeviceParcelable from a Parcel. */
@NonNull
public static final Creator<NearbyDeviceParcelable> CREATOR =
new Creator<NearbyDeviceParcelable>() {
@@ -54,8 +51,13 @@
builder.setName(in.readString());
}
builder.setMedium(in.readInt());
- builder.setRssi(in.readInt());
builder.setTxPower(in.readInt());
+ builder.setRssi(in.readInt());
+ builder.setAction(in.readInt());
+ builder.setPublicCredential(
+ in.readParcelable(
+ PublicCredential.class.getClassLoader(),
+ PublicCredential.class));
if (in.readInt() == 1) {
builder.setFastPairModelId(in.readString());
}
@@ -78,36 +80,40 @@
};
@ScanRequest.ScanType int mScanType;
- @Nullable
- private final String mName;
- @NearbyDevice.Medium
- private final int mMedium;
- private final int mRssi;
+ @Nullable private final String mName;
+ @NearbyDevice.Medium private final int mMedium;
private final int mTxPower;
+ private final int mRssi;
+ private final int mAction;
+ private final PublicCredential mPublicCredential;
+ @Nullable private final String mBluetoothAddress;
+ @Nullable private final String mFastPairModelId;
+ @Nullable private final byte[] mData;
- @Nullable
- private final String mBluetoothAddress;
- @Nullable
- private final String mFastPairModelId;
- @Nullable
- private final byte[] mData;
-
- private NearbyDeviceParcelable(@ScanRequest.ScanType int scanType, @Nullable String name,
- int medium, int rssi, int txPower, @Nullable String fastPairModelId,
- @Nullable String bluetoothAddress, @Nullable byte[] data) {
+ private NearbyDeviceParcelable(
+ @ScanRequest.ScanType int scanType,
+ @Nullable String name,
+ int medium,
+ int TxPower,
+ int rssi,
+ int action,
+ PublicCredential publicCredential,
+ @Nullable String fastPairModelId,
+ @Nullable String bluetoothAddress,
+ @Nullable byte[] data) {
mScanType = scanType;
mName = name;
mMedium = medium;
+ mTxPower = TxPower;
mRssi = rssi;
- mTxPower = txPower;
+ mAction = action;
+ mPublicCredential = publicCredential;
mFastPairModelId = fastPairModelId;
mBluetoothAddress = bluetoothAddress;
mData = data;
}
- /**
- * No special parcel contents.
- */
+ /** No special parcel contents. */
@Override
public int describeContents() {
return 0;
@@ -119,7 +125,6 @@
* @param dest The Parcel in which the object should be written.
* @param flags Additional flags about how the object should be written.
*/
-
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeInt(mName == null ? 0 : 1);
@@ -127,8 +132,10 @@
dest.writeString(mName);
}
dest.writeInt(mMedium);
- dest.writeInt(mRssi);
dest.writeInt(mTxPower);
+ dest.writeInt(mRssi);
+ dest.writeInt(mAction);
+ dest.writeParcelable(mPublicCredential, flags);
dest.writeInt(mFastPairModelId == null ? 0 : 1);
if (mFastPairModelId != null) {
dest.writeString(mFastPairModelId);
@@ -144,19 +151,26 @@
}
}
- /**
- * Returns a string representation of this ScanRequest.
- */
+ /** Returns a string representation of this ScanRequest. */
@Override
public String toString() {
return "NearbyDeviceParcelable["
- + "name=" + mName
- + ", medium=" + NearbyDevice.mediumToString(mMedium)
- + ", rssi=" + mRssi
- + ", txPower=" + mTxPower
- + ", bluetoothAddress=" + mBluetoothAddress
- + ", fastPairModelId=" + mFastPairModelId
- + ", data=" + Arrays.toString(mData)
+ + "name="
+ + mName
+ + ", medium="
+ + NearbyDevice.mediumToString(mMedium)
+ + ", txPower="
+ + mTxPower
+ + ", rssi="
+ + mRssi
+ + ", action="
+ + mAction
+ + ", bluetoothAddress="
+ + mBluetoothAddress
+ + ", fastPairModelId="
+ + mFastPairModelId
+ + ", data="
+ + Arrays.toString(mData)
+ "]";
}
@@ -164,10 +178,13 @@
public boolean equals(Object other) {
if (other instanceof NearbyDeviceParcelable) {
NearbyDeviceParcelable otherNearbyDeviceParcelable = (NearbyDeviceParcelable) other;
- return Objects.equals(mName, otherNearbyDeviceParcelable.mName)
+ return Objects.equals(mName, otherNearbyDeviceParcelable.mName)
&& (mMedium == otherNearbyDeviceParcelable.mMedium)
- && (mRssi == otherNearbyDeviceParcelable.mRssi)
&& (mTxPower == otherNearbyDeviceParcelable.mTxPower)
+ && (mRssi == otherNearbyDeviceParcelable.mRssi)
+ && (mAction == otherNearbyDeviceParcelable.mAction)
+ && (Objects.equals(
+ mPublicCredential, otherNearbyDeviceParcelable.mPublicCredential))
&& (Objects.equals(
mBluetoothAddress, otherNearbyDeviceParcelable.mBluetoothAddress))
&& (Objects.equals(
@@ -180,8 +197,14 @@
@Override
public int hashCode() {
return Objects.hash(
- mName, mMedium, mRssi, mTxPower, mBluetoothAddress,
- mFastPairModelId, Arrays.hashCode(mData));
+ mName,
+ mMedium,
+ mRssi,
+ mAction,
+ mPublicCredential.hashCode(),
+ mBluetoothAddress,
+ mFastPairModelId,
+ Arrays.hashCode(mData));
}
/**
@@ -194,9 +217,7 @@
return mScanType;
}
- /**
- * Gets the name of the NearbyDeviceParcelable. Returns {@code null} If there is no name.
- */
+ /** Gets the name of the NearbyDeviceParcelable. Returns {@code null} If there is no name. */
@Nullable
public String getName() {
return mName;
@@ -212,21 +233,39 @@
}
/**
- * Gets the received signal strength in dBm.
+ * Gets the transmission power in dBm.
+ *
+ * @hide
*/
@IntRange(from = -127, to = 126)
+ public int getTxPower() {
+ return mTxPower;
+ }
+
+ /** Gets the received signal strength in dBm. */
+ @IntRange(from = -127, to = 126)
public int getRssi() {
return mRssi;
}
/**
- * Gets the transmit power in dBm. A value of
- * android.bluetooth.le.ScanResult#TX_POWER_NOT_PRESENT
- * indicates that the TX power is not present.
+ * Gets the Action.
+ *
+ * @hide
*/
@IntRange(from = -127, to = 126)
- public int getTxPower() {
- return mTxPower;
+ public int getAction() {
+ return mAction;
+ }
+
+ /**
+ * Gets the public credential.
+ *
+ * @hide
+ */
+ @NonNull
+ public PublicCredential getPublicCredential() {
+ return mPublicCredential;
}
/**
@@ -247,31 +286,24 @@
return mBluetoothAddress;
}
- /**
- * Gets the raw data from the scanning. Returns {@code null} if there is no extra data.
- */
+ /** Gets the raw data from the scanning. Returns {@code null} if there is no extra data. */
@Nullable
public byte[] getData() {
return mData;
}
- /**
- * Builder class for {@link NearbyDeviceParcelable}.
- */
+ /** Builder class for {@link NearbyDeviceParcelable}. */
public static final class Builder {
- @Nullable
- private String mName;
- @NearbyDevice.Medium
- private int mMedium;
+ @Nullable private String mName;
+ @NearbyDevice.Medium private int mMedium;
+ private int mTxPower;
private int mRssi;
- private int mTxPower = ScanResult.TX_POWER_NOT_PRESENT;
+ private int mAction;
+ private PublicCredential mPublicCredential;
@ScanRequest.ScanType int mScanType;
- @Nullable
- private String mFastPairModelId;
- @Nullable
- private String mBluetoothAddress;
- @Nullable
- private byte[] mData;
+ @Nullable private String mFastPairModelId;
+ @Nullable private String mBluetoothAddress;
+ @Nullable private byte[] mData;
/**
* Sets the scan type of the NearbyDeviceParcelable.
@@ -306,6 +338,18 @@
}
/**
+ * Sets the transmission power of the discovered device.
+ *
+ * @param txPower The transmission power in dBm.
+ * @hide
+ */
+ @NonNull
+ public Builder setTxPower(int txPower) {
+ mTxPower = txPower;
+ return this;
+ }
+
+ /**
* Sets the RSSI between scanned device and the discovered device.
*
* @param rssi The received signal strength in dBm.
@@ -317,13 +361,26 @@
}
/**
- * Sets the txPower.
+ * Sets the action from the discovered device.
*
- * @param txPower The transmit power in dBm
+ * @param action The action of the discovered device.
+ * @hide
*/
@NonNull
- public Builder setTxPower(@IntRange(from = -127, to = 126) int txPower) {
- mTxPower = txPower;
+ public Builder setAction(int action) {
+ mAction = action;
+ return this;
+ }
+
+ /**
+ * Sets the public credential of the discovered device.
+ *
+ * @param publicCredential The public credential.
+ * @hide
+ */
+ @NonNull
+ public Builder setPublicCredential(@NonNull PublicCredential publicCredential) {
+ mPublicCredential = publicCredential;
return this;
}
@@ -352,8 +409,8 @@
/**
* Sets the scanned raw data.
*
- * @param data Data the scan.
- * For example, {@link ScanRecord#getServiceData()} if scanned by Bluetooth.
+ * @param data Data the scan. For example, {@link ScanRecord#getServiceData()} if scanned by
+ * Bluetooth.
*/
@NonNull
public Builder setData(@Nullable byte[] data) {
@@ -361,13 +418,20 @@
return this;
}
- /**
- * Builds a ScanResult.
- */
+ /** Builds a ScanResult. */
@NonNull
public NearbyDeviceParcelable build() {
- return new NearbyDeviceParcelable(mScanType, mName, mMedium, mRssi, mTxPower,
- mFastPairModelId, mBluetoothAddress, mData);
+ return new NearbyDeviceParcelable(
+ mScanType,
+ mName,
+ mMedium,
+ mTxPower,
+ mRssi,
+ mAction,
+ mPublicCredential,
+ mFastPairModelId,
+ mBluetoothAddress,
+ mData);
}
}
}
diff --git a/nearby/framework/java/android/nearby/PresenceCredential.java b/nearby/framework/java/android/nearby/PresenceCredential.java
index 7ad6ae9..1e851d6 100644
--- a/nearby/framework/java/android/nearby/PresenceCredential.java
+++ b/nearby/framework/java/android/nearby/PresenceCredential.java
@@ -24,7 +24,9 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
+import java.util.Objects;
/**
* Represents a credential for Nearby Presence.
@@ -33,50 +35,43 @@
*/
@SystemApi
public abstract class PresenceCredential {
- /**
- * Private credential type.
- */
+ /** Private credential type. */
public static final int CREDENTIAL_TYPE_PRIVATE = 0;
- /**
- * Public credential type.
- */
+ /** Public credential type. */
public static final int CREDENTIAL_TYPE_PUBLIC = 1;
- /** @hide **/
+ /**
+ * @hide *
+ */
@Retention(RetentionPolicy.SOURCE)
@IntDef({CREDENTIAL_TYPE_PUBLIC, CREDENTIAL_TYPE_PRIVATE})
- public @interface CredentialType {
- }
+ public @interface CredentialType {}
- /**
- * Unknown identity type.
- */
+ /** Unknown identity type. */
public static final int IDENTITY_TYPE_UNKNOWN = 0;
- /**
- * Private identity type.
- */
+ /** Private identity type. */
public static final int IDENTITY_TYPE_PRIVATE = 1;
- /**
- * Provisioned identity type.
- */
+ /** Provisioned identity type. */
public static final int IDENTITY_TYPE_PROVISIONED = 2;
- /**
- * Trusted identity type.
- */
+ /** Trusted identity type. */
public static final int IDENTITY_TYPE_TRUSTED = 3;
- /**
- * Public identity type.
- */
+ /** Public identity type. */
public static final int IDENTITY_TYPE_PUBLIC = 4;
- /** @hide **/
+ /**
+ * @hide *
+ */
@Retention(RetentionPolicy.SOURCE)
- @IntDef({IDENTITY_TYPE_UNKNOWN, IDENTITY_TYPE_PRIVATE, IDENTITY_TYPE_PROVISIONED,
- IDENTITY_TYPE_TRUSTED, IDENTITY_TYPE_PUBLIC})
- public @interface IdentityType {
- }
+ @IntDef({
+ IDENTITY_TYPE_UNKNOWN,
+ IDENTITY_TYPE_PRIVATE,
+ IDENTITY_TYPE_PROVISIONED,
+ IDENTITY_TYPE_TRUSTED,
+ IDENTITY_TYPE_PUBLIC
+ })
+ public @interface IdentityType {}
private final @CredentialType int mType;
private final @IdentityType int mIdentityType;
@@ -84,8 +79,12 @@
private final byte[] mAuthenticityKey;
private final List<CredentialElement> mCredentialElements;
- PresenceCredential(@CredentialType int type, @IdentityType int identityType,
- byte[] secretId, byte[] authenticityKey, List<CredentialElement> credentialElements) {
+ PresenceCredential(
+ @CredentialType int type,
+ @IdentityType int identityType,
+ byte[] secretId,
+ byte[] authenticityKey,
+ List<CredentialElement> credentialElements) {
mType = type;
mIdentityType = identityType;
mSecretId = secretId;
@@ -101,48 +100,63 @@
mAuthenticityKey = new byte[in.readInt()];
in.readByteArray(mAuthenticityKey);
mCredentialElements = new ArrayList<>();
- in.readList(mCredentialElements, CredentialElement.class.getClassLoader(),
+ in.readList(
+ mCredentialElements,
+ CredentialElement.class.getClassLoader(),
CredentialElement.class);
}
- /**
- * Returns the type of the credential.
- */
+ /** Returns the type of the credential. */
public @CredentialType int getType() {
return mType;
}
- /**
- * Returns the identity type of the credential.
- */
+ /** Returns the identity type of the credential. */
public @IdentityType int getIdentityType() {
return mIdentityType;
}
- /**
- * Returns the secret id of the credential.
- */
+ /** Returns the secret id of the credential. */
@NonNull
public byte[] getSecretId() {
return mSecretId;
}
- /**
- * Returns the authenticity key of the credential.
- */
+ /** Returns the authenticity key of the credential. */
@NonNull
public byte[] getAuthenticityKey() {
return mAuthenticityKey;
}
- /**
- * Returns the elements of the credential.
- */
+ /** Returns the elements of the credential. */
@NonNull
public List<CredentialElement> getCredentialElements() {
return mCredentialElements;
}
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof PresenceCredential) {
+ PresenceCredential that = (PresenceCredential) obj;
+ return mType == that.mType
+ && mIdentityType == that.mIdentityType
+ && Arrays.equals(mSecretId, that.mSecretId)
+ && Arrays.equals(mAuthenticityKey, that.mAuthenticityKey)
+ && mCredentialElements.equals(that.mCredentialElements);
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(
+ mType,
+ mIdentityType,
+ Arrays.hashCode(mSecretId),
+ Arrays.hashCode(mAuthenticityKey),
+ mCredentialElements.hashCode());
+ }
+
/**
* Writes the presence credential to the parcel.
*
diff --git a/nearby/framework/java/android/nearby/PublicCredential.java b/nearby/framework/java/android/nearby/PublicCredential.java
index 8aac323..5998d19 100644
--- a/nearby/framework/java/android/nearby/PublicCredential.java
+++ b/nearby/framework/java/android/nearby/PublicCredential.java
@@ -17,6 +17,7 @@
package android.nearby;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
@@ -24,6 +25,7 @@
import com.android.internal.util.Preconditions;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
import java.util.Objects;
@@ -35,25 +37,31 @@
@SystemApi
public final class PublicCredential extends PresenceCredential implements Parcelable {
@NonNull
- public static final Creator<PublicCredential> CREATOR = new Creator<PublicCredential>() {
- @Override
- public PublicCredential createFromParcel(Parcel in) {
- in.readInt(); // Skip the type as it's used by parent class only.
- return createFromParcelBody(in);
- }
+ public static final Creator<PublicCredential> CREATOR =
+ new Creator<PublicCredential>() {
+ @Override
+ public PublicCredential createFromParcel(Parcel in) {
+ in.readInt(); // Skip the type as it's used by parent class only.
+ return createFromParcelBody(in);
+ }
- @Override
- public PublicCredential[] newArray(int size) {
- return new PublicCredential[size];
- }
- };
+ @Override
+ public PublicCredential[] newArray(int size) {
+ return new PublicCredential[size];
+ }
+ };
private final byte[] mPublicKey;
private final byte[] mEncryptedMetadata;
private final byte[] mEncryptedMetadataKeyTag;
- private PublicCredential(int identityType, byte[] secretId, byte[] authenticityKey,
- List<CredentialElement> credentialElements, byte[] publicKey, byte[] encryptedMetadata,
+ private PublicCredential(
+ int identityType,
+ byte[] secretId,
+ byte[] authenticityKey,
+ List<CredentialElement> credentialElements,
+ byte[] publicKey,
+ byte[] encryptedMetadata,
byte[] metadataEncryptionKeyTag) {
super(CREDENTIAL_TYPE_PUBLIC, identityType, secretId, authenticityKey, credentialElements);
mPublicKey = publicKey;
@@ -75,25 +83,19 @@
return new PublicCredential(in);
}
- /**
- * Returns the public key associated with this credential.
- */
+ /** Returns the public key associated with this credential. */
@NonNull
public byte[] getPublicKey() {
return mPublicKey;
}
- /**
- * Returns the encrypted metadata associated with this credential.
- */
+ /** Returns the encrypted metadata associated with this credential. */
@NonNull
public byte[] getEncryptedMetadata() {
return mEncryptedMetadata;
}
- /**
- * Returns the metadata encryption key tag associated with this credential.
- */
+ /** Returns the metadata encryption key tag associated with this credential. */
@NonNull
public byte[] getEncryptedMetadataKeyTag() {
return mEncryptedMetadataKeyTag;
@@ -105,6 +107,27 @@
}
@Override
+ public boolean equals(@Nullable Object obj) {
+ if (obj instanceof PublicCredential) {
+ PublicCredential that = (PublicCredential) obj;
+ return super.equals(obj)
+ && Arrays.equals(mPublicKey, that.mPublicKey)
+ && Arrays.equals(mEncryptedMetadata, that.mEncryptedMetadata)
+ && Arrays.equals(mEncryptedMetadataKeyTag, that.mEncryptedMetadataKeyTag);
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(
+ super.hashCode(),
+ Arrays.hashCode(mPublicKey),
+ Arrays.hashCode(mEncryptedMetadata),
+ Arrays.hashCode(mEncryptedMetadataKeyTag));
+ }
+
+ @Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
super.writeToParcel(dest, flags);
dest.writeInt(mPublicKey.length);
@@ -115,9 +138,7 @@
dest.writeByteArray(mEncryptedMetadataKeyTag);
}
- /**
- * Builder class for {@link PresenceCredential}.
- */
+ /** Builder class for {@link PresenceCredential}. */
public static final class Builder {
private final List<CredentialElement> mCredentialElements;
@@ -128,17 +149,21 @@
private final byte[] mEncryptedMetadata;
private final byte[] mEncryptedMetadataKeyTag;
- public Builder(@NonNull byte[] secretId, @NonNull byte[] authenticityKey,
- @NonNull byte[] publicKey, @NonNull byte[] encryptedMetadata,
+ public Builder(
+ @NonNull byte[] secretId,
+ @NonNull byte[] authenticityKey,
+ @NonNull byte[] publicKey,
+ @NonNull byte[] encryptedMetadata,
@NonNull byte[] encryptedMetadataKeyTag) {
- Preconditions.checkState(secretId != null && secretId.length > 0,
- "secret id cannot be empty");
- Preconditions.checkState(authenticityKey != null && authenticityKey.length > 0,
+ Preconditions.checkState(
+ secretId != null && secretId.length > 0, "secret id cannot be empty");
+ Preconditions.checkState(
+ authenticityKey != null && authenticityKey.length > 0,
"authenticity key cannot be empty");
Preconditions.checkState(
- publicKey != null && publicKey.length > 0,
- "publicKey cannot be empty");
- Preconditions.checkState(encryptedMetadata != null && encryptedMetadata.length > 0,
+ publicKey != null && publicKey.length > 0, "publicKey cannot be empty");
+ Preconditions.checkState(
+ encryptedMetadata != null && encryptedMetadata.length > 0,
"encryptedMetadata cannot be empty");
Preconditions.checkState(
encryptedMetadataKeyTag != null && encryptedMetadataKeyTag.length > 0,
@@ -152,18 +177,14 @@
mCredentialElements = new ArrayList<>();
}
- /**
- * Sets the identity type for the presence credential.
- */
+ /** Sets the identity type for the presence credential. */
@NonNull
public Builder setIdentityType(@IdentityType int identityType) {
mIdentityType = identityType;
return this;
}
- /**
- * Adds an element to the credential.
- */
+ /** Adds an element to the credential. */
@NonNull
public Builder addCredentialElement(@NonNull CredentialElement credentialElement) {
Objects.requireNonNull(credentialElement);
@@ -171,14 +192,17 @@
return this;
}
- /**
- * Builds the {@link PresenceCredential}.
- */
+ /** Builds the {@link PresenceCredential}. */
@NonNull
public PublicCredential build() {
- return new PublicCredential(mIdentityType, mSecretId, mAuthenticityKey,
- mCredentialElements, mPublicKey, mEncryptedMetadata, mEncryptedMetadataKeyTag);
+ return new PublicCredential(
+ mIdentityType,
+ mSecretId,
+ mAuthenticityKey,
+ mCredentialElements,
+ mPublicKey,
+ mEncryptedMetadata,
+ mEncryptedMetadataKeyTag);
}
-
}
}
diff --git a/nearby/service/java/com/android/server/nearby/NearbyService.java b/nearby/service/java/com/android/server/nearby/NearbyService.java
index d721575..e3e5b5d 100644
--- a/nearby/service/java/com/android/server/nearby/NearbyService.java
+++ b/nearby/service/java/com/android/server/nearby/NearbyService.java
@@ -39,16 +39,11 @@
import com.android.server.nearby.fastpair.FastPairManager;
import com.android.server.nearby.injector.ContextHubManagerAdapter;
import com.android.server.nearby.injector.Injector;
-import com.android.server.nearby.presence.ChreCommunication;
import com.android.server.nearby.presence.PresenceManager;
import com.android.server.nearby.provider.BroadcastProviderManager;
import com.android.server.nearby.provider.DiscoveryProviderManager;
import com.android.server.nearby.provider.FastPairDataProvider;
-import java.util.concurrent.Executors;
-
-import service.proto.Blefilter;
-
/** Service implementing nearby functionality. */
public class NearbyService extends INearbyManager.Stub {
public static final String TAG = "NearbyService";
@@ -84,19 +79,7 @@
mBroadcastProviderManager = new BroadcastProviderManager(context, mSystemInjector);
final LocatorContextWrapper lcw = new LocatorContextWrapper(context, null);
mFastPairManager = new FastPairManager(lcw);
- mPresenceManager =
- new PresenceManager(
- mContext,
- (results) -> {
- // TODO(b/221082271): hooked with API codes.
- for (Blefilter.BleFilterResult result : results.getResultList()) {
- Log.i(
- TAG,
- String.format(
- "received filter result with id: %d",
- result.getId()));
- }
- });
+ mPresenceManager = new PresenceManager(lcw);
}
@Override
@@ -144,10 +127,9 @@
mBluetoothReceiver,
new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED));
mFastPairManager.initiate();
+ // Initialize ContextManager for CHRE scan.
mSystemInjector.initializeContextHubManagerAdapter();
- mPresenceManager.initiate(
- new ChreCommunication(
- mSystemInjector, Executors.newSingleThreadExecutor()));
+ mPresenceManager.initiate();
break;
}
}
@@ -155,7 +137,7 @@
private static final class SystemInjector implements Injector {
private final Context mContext;
@Nullable private BluetoothAdapter mBluetoothAdapter;
- @Nullable private ContextHubManagerAdapter mContextHubManagerAdapter;
+ @Nullable private ContextHubManagerAdapter mContextHubManagerAdapter;
SystemInjector(Context context) {
mContext = context;
@@ -168,6 +150,7 @@
}
@Override
+ @Nullable
public ContextHubManagerAdapter getContextHubManagerAdapter() {
return mContextHubManagerAdapter;
}
@@ -193,6 +176,5 @@
}
mContextHubManagerAdapter = new ContextHubManagerAdapter(manager);
}
-
}
}
diff --git a/nearby/service/java/com/android/server/nearby/presence/PresenceDiscoveryResult.java b/nearby/service/java/com/android/server/nearby/presence/PresenceDiscoveryResult.java
index e48074d..80ad88d 100644
--- a/nearby/service/java/com/android/server/nearby/presence/PresenceDiscoveryResult.java
+++ b/nearby/service/java/com/android/server/nearby/presence/PresenceDiscoveryResult.java
@@ -17,6 +17,7 @@
package com.android.server.nearby.presence;
import android.nearby.NearbyDevice;
+import android.nearby.NearbyDeviceParcelable;
import android.nearby.PresenceDevice;
import android.nearby.PresenceScanFilter;
import android.nearby.PublicCredential;
@@ -24,16 +25,17 @@
import java.util.ArrayList;
import java.util.List;
-/**
- * Represents a Presence discovery result.
- */
+/** Represents a Presence discovery result. */
public class PresenceDiscoveryResult {
- /**
- * Creates a {@link PresenceDiscoveryResult} from the scan data.
- */
- public static PresenceDiscoveryResult fromScanData(byte[] scanData, int rssi) {
- return new PresenceDiscoveryResult.Builder().setRssi(rssi).build();
+ /** Creates a {@link PresenceDiscoveryResult} from the scan data. */
+ public static PresenceDiscoveryResult fromDevice(NearbyDeviceParcelable device) {
+ return new PresenceDiscoveryResult.Builder()
+ .setTxPower(device.getTxPower())
+ .setRssi(device.getRssi())
+ .addPresenceAction(device.getAction())
+ .setPublicCredential(device.getPublicCredential())
+ .build();
}
private final int mTxPower;
@@ -42,8 +44,12 @@
private final List<Integer> mPresenceActions;
private final PublicCredential mPublicCredential;
- private PresenceDiscoveryResult(int txPower, int rssi, byte[] salt,
- List<Integer> presenceActions, PublicCredential publicCredential) {
+ private PresenceDiscoveryResult(
+ int txPower,
+ int rssi,
+ byte[] salt,
+ List<Integer> presenceActions,
+ PublicCredential publicCredential) {
mTxPower = txPower;
mRssi = rssi;
mSalt = salt;
@@ -51,9 +57,7 @@
mPublicCredential = publicCredential;
}
- /**
- * Returns whether the discovery result matches the scan filter.
- */
+ /** Returns whether the discovery result matches the scan filter. */
public boolean matches(PresenceScanFilter scanFilter) {
return pathLossMatches(scanFilter.getMaxPathLoss())
&& actionMatches(scanFilter.getPresenceActions())
@@ -75,9 +79,7 @@
return credentials.contains(mPublicCredential);
}
- /**
- * Converts a presence device from the discovery result.
- */
+ /** Converts a presence device from the discovery result. */
public PresenceDevice toPresenceDevice() {
return new PresenceDevice.Builder(
// Use the public credential hash as the device Id.
@@ -86,12 +88,11 @@
mPublicCredential.getSecretId(),
mPublicCredential.getEncryptedMetadata())
.setRssi(mRssi)
- .addMedium(NearbyDevice.Medium.BLE).build();
+ .addMedium(NearbyDevice.Medium.BLE)
+ .build();
}
- /**
- * Builder for {@link PresenceDiscoveryResult}.
- */
+ /** Builder for {@link PresenceDiscoveryResult}. */
public static class Builder {
private int mTxPower;
private int mRssi;
@@ -104,52 +105,40 @@
mPresenceActions = new ArrayList<>();
}
- /**
- * Sets the calibrated tx power for the discovery result.
- */
+ /** Sets the calibrated tx power for the discovery result. */
public Builder setTxPower(int txPower) {
mTxPower = txPower;
return this;
}
- /**
- * Sets the rssi for the discovery result.
- */
+ /** Sets the rssi for the discovery result. */
public Builder setRssi(int rssi) {
mRssi = rssi;
return this;
}
- /**
- * Sets the salt for the discovery result.
- */
+ /** Sets the salt for the discovery result. */
public Builder setSalt(byte[] salt) {
mSalt = salt;
return this;
}
- /**
- * Sets the public credential for the discovery result.
- */
+ /** Sets the public credential for the discovery result. */
public Builder setPublicCredential(PublicCredential publicCredential) {
mPublicCredential = publicCredential;
return this;
}
- /**
- * Adds presence action of the discovery result.
- */
+ /** Adds presence action of the discovery result. */
public Builder addPresenceAction(int presenceAction) {
mPresenceActions.add(presenceAction);
return this;
}
- /**
- * Builds a {@link PresenceDiscoveryResult}.
- */
+ /** Builds a {@link PresenceDiscoveryResult}. */
public PresenceDiscoveryResult build() {
- return new PresenceDiscoveryResult(mTxPower, mRssi, mSalt, mPresenceActions,
- mPublicCredential);
+ return new PresenceDiscoveryResult(
+ mTxPower, mRssi, mSalt, mPresenceActions, mPublicCredential);
}
}
}
diff --git a/nearby/service/java/com/android/server/nearby/presence/PresenceManager.java b/nearby/service/java/com/android/server/nearby/presence/PresenceManager.java
index 66d4864..382c47a 100644
--- a/nearby/service/java/com/android/server/nearby/presence/PresenceManager.java
+++ b/nearby/service/java/com/android/server/nearby/presence/PresenceManager.java
@@ -16,152 +16,121 @@
package com.android.server.nearby.presence;
+import static com.android.server.nearby.NearbyService.TAG;
+
+import android.annotation.Nullable;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
-import android.hardware.location.NanoAppMessage;
+import android.nearby.NearbyDevice;
+import android.nearby.NearbyManager;
+import android.nearby.PresenceScanFilter;
+import android.nearby.PublicCredential;
+import android.nearby.ScanCallback;
+import android.nearby.ScanRequest;
import android.util.Log;
-import com.android.internal.annotations.VisibleForTesting;
+import androidx.annotation.NonNull;
-import com.google.protobuf.ByteString;
-import com.google.protobuf.InvalidProtocolBufferException;
+import com.android.server.nearby.common.locator.Locator;
+import com.android.server.nearby.common.locator.LocatorContextWrapper;
-import java.util.Collections;
-
-import service.proto.Blefilter;
+import java.util.Locale;
+import java.util.concurrent.Executors;
/** PresenceManager is the class initiated in nearby service to handle presence related work. */
public class PresenceManager {
- /** Callback that receives filter results from CHRE Nanoapp. */
- public interface PresenceCallback {
- /** Called when {@link BleFilterResults} has been received. */
- void onFilterResults(Blefilter.BleFilterResults filterResults);
- }
- private static final String TAG = "PresenceService";
- // Nanoapp ID reserved for Nearby Presence.
- /** @hide */
- @VisibleForTesting
- public static final long NANOAPP_ID = 0x476f6f676c001031L;
- /** @hide */
- @VisibleForTesting
- public static final int NANOAPP_MESSAGE_TYPE_FILTER = 3;
- /** @hide */
- @VisibleForTesting
- public static final int NANOAPP_MESSAGE_TYPE_FILTER_RESULT = 4;
- private final Context mContext;
- private final PresenceCallback mPresenceCallback;
- private final ChreCallback mChreCallback;
- private ChreCommunication mChreCommunication;
-
- private Blefilter.BleFilters mFilters = null;
- private boolean mChreStarted = false;
-
+ final LocatorContextWrapper mLocatorContextWrapper;
+ final Locator mLocator;
private final IntentFilter mIntentFilter;
+ private final ScanCallback mScanCallback =
+ new ScanCallback() {
+ @Override
+ public void onDiscovered(@NonNull NearbyDevice device) {
+ Log.i(TAG, "[PresenceManager] discovered Device.");
+ }
+
+ @Override
+ public void onUpdated(@NonNull NearbyDevice device) {}
+
+ @Override
+ public void onLost(@NonNull NearbyDevice device) {}
+ };
+
private final BroadcastReceiver mScreenBroadcastReceiver =
new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
+ NearbyManager manager = getNearbyManager();
+ if (manager == null) {
+ Log.e(TAG, "Nearby Manager is null");
+ return;
+ }
if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
- // TODO(b/221082271): removed this faked data once hooked with API codes.
- Log.d(TAG, "Update Presence CHRE filter");
- ByteString mac_addr = ByteString.copyFrom(new byte[] {1, 2, 3, 4, 5, 6});
- Blefilter.BleFilter filter =
- Blefilter.BleFilter.newBuilder()
- .setId(0)
- .setUuid(0xFCF1)
- .setIntent(1)
- .setMacAddress(mac_addr)
+ Log.d(TAG, "Start CHRE scan.");
+ byte[] secreteId = {1, 0, 0, 0};
+ byte[] authenticityKey = {2, 0, 0, 0};
+ byte[] publicKey = {3, 0, 0, 0};
+ byte[] encryptedMetaData = {4, 0, 0, 0};
+ byte[] encryptedMetaDataTag = {5, 0, 0, 0};
+ PublicCredential publicCredential =
+ new PublicCredential.Builder(
+ secreteId,
+ authenticityKey,
+ publicKey,
+ encryptedMetaData,
+ encryptedMetaDataTag)
.build();
- Blefilter.BleFilters filters =
- Blefilter.BleFilters.newBuilder().addFilter(filter).build();
- updateFilters(filters);
+ PresenceScanFilter presenceScanFilter =
+ new PresenceScanFilter.Builder()
+ .setMaxPathLoss(3)
+ .addCredential(publicCredential)
+ .addPresenceAction(1)
+ .build();
+ ScanRequest scanRequest =
+ new ScanRequest.Builder()
+ .setScanType(ScanRequest.SCAN_TYPE_NEARBY_PRESENCE)
+ .addScanFilter(presenceScanFilter)
+ .build();
+ Log.i(
+ TAG,
+ String.format(
+ Locale.getDefault(),
+ "[PresenceManager] Start Presence scan with request: %s",
+ scanRequest.toString()));
+ manager.startScan(
+ scanRequest, Executors.newSingleThreadExecutor(), mScanCallback);
+ } else if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
+ Log.d(TAG, "Stop CHRE scan.");
+ manager.stopScan(mScanCallback);
}
}
};
- public PresenceManager(Context context, PresenceCallback presenceCallback) {
- mContext = context;
- mPresenceCallback = presenceCallback;
- mChreCallback = new ChreCallback();
+ public PresenceManager(LocatorContextWrapper contextWrapper) {
+ mLocatorContextWrapper = contextWrapper;
+ mLocator = mLocatorContextWrapper.getLocator();
mIntentFilter = new IntentFilter();
}
+ /** Null when the Nearby Service is not available. */
+ @Nullable
+ private NearbyManager getNearbyManager() {
+ return (NearbyManager)
+ mLocatorContextWrapper
+ .getApplicationContext()
+ .getSystemService(Context.NEARBY_SERVICE);
+ }
+
/** Function called when nearby service start. */
- public void initiate(ChreCommunication chreCommunication) {
- mChreCommunication = chreCommunication;
- mChreCommunication.start(mChreCallback, Collections.singleton(NANOAPP_ID));
-
+ public void initiate() {
mIntentFilter.addAction(Intent.ACTION_SCREEN_ON);
- mContext.registerReceiver(mScreenBroadcastReceiver, mIntentFilter);
- }
-
- /** Updates the fitlers in Context Hub. */
- public synchronized void updateFilters(Blefilter.BleFilters filters) {
- mFilters = filters;
- if (mChreStarted) {
- sendFilters(mFilters);
- mFilters = null;
- }
- }
-
- private void sendFilters(Blefilter.BleFilters filters) {
- NanoAppMessage message =
- NanoAppMessage.createMessageToNanoApp(
- NANOAPP_ID, NANOAPP_MESSAGE_TYPE_FILTER, filters.toByteArray());
- if (!mChreCommunication.sendMessageToNanoApp(message)) {
- Log.e(TAG, "Failed to send filters to CHRE.");
- }
- }
-
- private class ChreCallback implements ChreCommunication.ContextHubCommsCallback {
-
- @Override
- public void started(boolean success) {
- if (success) {
- synchronized (PresenceManager.this) {
- Log.i(TAG, "CHRE communication started");
- mChreStarted = true;
- if (mFilters != null) {
- sendFilters(mFilters);
- mFilters = null;
- }
- }
- }
- }
-
- @Override
- public void onHubReset() {
- // TODO(b/221082271): hooked with upper level codes.
- Log.i(TAG, "CHRE reset.");
- }
-
- @Override
- public void onNanoAppRestart(long nanoAppId) {
- // TODO(b/221082271): hooked with upper level codes.
- Log.i(TAG, String.format("CHRE NanoApp %d restart.", nanoAppId));
- }
-
- @Override
- public void onMessageFromNanoApp(NanoAppMessage message) {
- if (message.getNanoAppId() != NANOAPP_ID) {
- Log.e(TAG, "Received message from unknown nano app.");
- return;
- }
- if (message.getMessageType() == NANOAPP_MESSAGE_TYPE_FILTER_RESULT) {
- try {
- Blefilter.BleFilterResults results =
- Blefilter.BleFilterResults.parseFrom(message.getMessageBody());
- mPresenceCallback.onFilterResults(results);
- } catch (InvalidProtocolBufferException e) {
- Log.e(
- TAG,
- String.format("Failed to decode the filter result %s", e.toString()));
- }
- }
- }
+ mIntentFilter.addAction(Intent.ACTION_SCREEN_OFF);
+ mLocatorContextWrapper
+ .getContext()
+ .registerReceiver(mScreenBroadcastReceiver, mIntentFilter);
}
}
diff --git a/nearby/service/java/com/android/server/nearby/provider/AbstractDiscoveryProvider.java b/nearby/service/java/com/android/server/nearby/provider/AbstractDiscoveryProvider.java
index 7cc859c..f136695 100644
--- a/nearby/service/java/com/android/server/nearby/provider/AbstractDiscoveryProvider.java
+++ b/nearby/service/java/com/android/server/nearby/provider/AbstractDiscoveryProvider.java
@@ -20,11 +20,13 @@
import android.content.Context;
import android.nearby.NearbyDeviceParcelable;
+import android.nearby.ScanFilter;
import android.nearby.ScanRequest;
import android.util.Log;
import androidx.annotation.Nullable;
+import java.util.List;
import java.util.concurrent.Executor;
/**
@@ -38,10 +40,9 @@
protected final DiscoveryProviderController mController;
protected final Executor mExecutor;
protected Listener mListener;
+ protected List<ScanFilter> mScanFilters;
- /**
- * Interface for listening to discovery providers.
- */
+ /** Interface for listening to discovery providers. */
public interface Listener {
/**
* Called when a provider has a new nearby device available. May be invoked from any thread.
@@ -60,20 +61,20 @@
* can now be expected. Always implies that the provider request is set to the empty request.
* Always invoked on the provider executor.
*/
- protected void onStart() { }
+ protected void onStart() {}
/**
* Callback invoked when the provider is stopped, and signals that no further callback
* invocations will occur (until a further call to {@link #onStart()}. Always invoked on the
* provider executor.
*/
- protected void onStop() { }
+ protected void onStop() {}
/**
* Callback invoked to inform the provider of a new provider request which replaces any prior
* provider request. Always invoked on the provider executor.
*/
- protected void invalidateScanMode() { }
+ protected void invalidateScanMode() {}
/**
* Retrieves the controller for this discovery provider. Should never be invoked by subclasses,
@@ -134,5 +135,10 @@
public int getProviderScanMode() {
return mScanMode;
}
+
+ @Override
+ public void setProviderScanFilters(List<ScanFilter> filters) {
+ mScanFilters = filters;
+ }
}
}
diff --git a/nearby/service/java/com/android/server/nearby/presence/ChreCommunication.java b/nearby/service/java/com/android/server/nearby/provider/ChreCommunication.java
similarity index 91%
rename from nearby/service/java/com/android/server/nearby/presence/ChreCommunication.java
rename to nearby/service/java/com/android/server/nearby/provider/ChreCommunication.java
index fc9863e..607c579 100644
--- a/nearby/service/java/com/android/server/nearby/presence/ChreCommunication.java
+++ b/nearby/service/java/com/android/server/nearby/provider/ChreCommunication.java
@@ -14,7 +14,9 @@
* limitations under the License.
*/
-package com.android.server.nearby.presence;
+package com.android.server.nearby.provider;
+
+import static com.android.server.nearby.NearbyService.TAG;
import android.annotation.Nullable;
import android.hardware.location.ContextHubClient;
@@ -60,8 +62,7 @@
void onMessageFromNanoApp(NanoAppMessage message);
}
- public static final String TAG = "PresenceService";
- @Nullable private final ContextHubManagerAdapter mManager;
+ private final Injector mInjector;
private final Executor mExecutor;
private boolean mStarted = false;
@@ -69,10 +70,14 @@
@Nullable private ContextHubClient mContextHubClient;
public ChreCommunication(Injector injector, Executor executor) {
- this.mManager = injector.getContextHubManagerAdapter();
+ mInjector = injector;
mExecutor = executor;
}
+ public boolean available() {
+ return mInjector.getContextHubManagerAdapter() != null;
+ }
+
/**
* Starts communication with the contexthub. This will invoke {@link
* ContextHubCommsCallback#start(boolean)} on completion.
@@ -81,18 +86,17 @@
* contexthub.
*/
public synchronized void start(ContextHubCommsCallback callback, Set<Long> nanoAppIds) {
- if (this.mManager == null) {
+ ContextHubManagerAdapter manager = mInjector.getContextHubManagerAdapter();
+ if (manager == null) {
Log.e(TAG, "ContexHub not available in this device");
return;
} else {
Log.i(TAG, "Start ChreCommunication");
}
Preconditions.checkNotNull(callback);
- if (nanoAppIds.isEmpty() || mManager == null) {
- callback.started(false);
- return;
- }
+ Preconditions.checkArgument(!nanoAppIds.isEmpty());
if (mStarted) {
+ Log.i(TAG, "ChreCommunication already started");
this.mCallback.started(true);
return;
}
@@ -102,17 +106,18 @@
mStarted = true;
this.mCallback = callback;
- List<ContextHubInfo> contextHubs = mManager.getContextHubs();
+ List<ContextHubInfo> contextHubs = manager.getContextHubs();
// Make a copy of the list so we can modify it during our async callbacks (in case the code
// is still iterating)
List<ContextHubInfo> validContextHubs = new ArrayList<>(contextHubs);
for (ContextHubInfo info : contextHubs) {
- ContextHubTransaction<List<NanoAppState>> transaction = mManager.queryNanoApps(info);
+ ContextHubTransaction<List<NanoAppState>> transaction = manager.queryNanoApps(info);
Log.i(TAG, "After query Nano Apps ");
transaction.setOnCompleteListener(
- new OnQueryCompleteListener(info, validContextHubs, nanoAppIds), mExecutor);
+ new OnQueryCompleteListener(info, validContextHubs, nanoAppIds, manager),
+ mExecutor);
}
}
@@ -202,14 +207,17 @@
private final ContextHubInfo mQueriedContextHub;
private final List<ContextHubInfo> mContextHubs;
private final Set<Long> mNanoAppIds;
+ private final ContextHubManagerAdapter mManager;
OnQueryCompleteListener(
ContextHubInfo queriedContextHub,
List<ContextHubInfo> contextHubs,
- Set<Long> nanoAppIds) {
+ Set<Long> nanoAppIds,
+ ContextHubManagerAdapter manager) {
this.mQueriedContextHub = queriedContextHub;
this.mContextHubs = contextHubs;
this.mNanoAppIds = nanoAppIds;
+ this.mManager = manager;
}
@Override
diff --git a/nearby/service/java/com/android/server/nearby/provider/ChreDiscoveryProvider.java b/nearby/service/java/com/android/server/nearby/provider/ChreDiscoveryProvider.java
new file mode 100644
index 0000000..a70ef13
--- /dev/null
+++ b/nearby/service/java/com/android/server/nearby/provider/ChreDiscoveryProvider.java
@@ -0,0 +1,194 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.nearby.provider;
+
+import static android.nearby.ScanRequest.SCAN_TYPE_NEARBY_PRESENCE;
+
+import static com.android.server.nearby.NearbyService.TAG;
+
+import android.content.Context;
+import android.hardware.location.NanoAppMessage;
+import android.nearby.NearbyDevice;
+import android.nearby.NearbyDeviceParcelable;
+import android.nearby.PresenceScanFilter;
+import android.nearby.PublicCredential;
+import android.nearby.ScanFilter;
+import android.util.Log;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import com.google.protobuf.InvalidProtocolBufferException;
+
+import service.proto.Blefilter;
+
+import java.util.Collections;
+import java.util.concurrent.Executor;
+
+/** Discovery provider that uses CHRE Nearby Nanoapp to do scanning. */
+public class ChreDiscoveryProvider extends AbstractDiscoveryProvider {
+ // Nanoapp ID reserved for Nearby Presence.
+ /** @hide */
+ @VisibleForTesting public static final long NANOAPP_ID = 0x476f6f676c001031L;
+ /** @hide */
+ @VisibleForTesting public static final int NANOAPP_MESSAGE_TYPE_FILTER = 3;
+ /** @hide */
+ @VisibleForTesting public static final int NANOAPP_MESSAGE_TYPE_FILTER_RESULT = 4;
+
+ private static final int PRESENCE_UUID = 0xFCF1;
+
+ private ChreCommunication mChreCommunication;
+ private ChreCallback mChreCallback;
+ private boolean mChreStarted = false;
+ private Blefilter.BleFilters mFilters = null;
+ private int mFilterId;
+
+ public ChreDiscoveryProvider(
+ Context context, ChreCommunication chreCommunication, Executor executor) {
+ super(context, executor);
+ mChreCommunication = chreCommunication;
+ mChreCallback = new ChreCallback();
+ mFilterId = 0;
+ }
+
+ @Override
+ protected void onStart() {
+ Log.d(TAG, "Start CHRE scan");
+ mChreCommunication.start(mChreCallback, Collections.singleton(NANOAPP_ID));
+ updateFilters();
+ }
+
+ @Override
+ protected void onStop() {
+ mChreStarted = false;
+ mChreCommunication.stop();
+ }
+
+ @Override
+ protected void invalidateScanMode() {
+ onStop();
+ onStart();
+ }
+
+ public boolean available() {
+ return mChreCommunication.available();
+ }
+
+ private synchronized void updateFilters() {
+ if (mScanFilters == null) {
+ Log.e(TAG, "ScanFilters not set.");
+ return;
+ }
+ Blefilter.BleFilters.Builder filtersBuilder = Blefilter.BleFilters.newBuilder();
+ for (ScanFilter scanFilter : mScanFilters) {
+ PresenceScanFilter presenceScanFilter = (PresenceScanFilter) scanFilter;
+ Blefilter.BleFilter filter =
+ Blefilter.BleFilter.newBuilder()
+ .setId(mFilterId)
+ .setUuid(PRESENCE_UUID)
+ .setIntent(presenceScanFilter.getPresenceActions().get(0))
+ .build();
+ filtersBuilder.addFilter(filter);
+ mFilterId++;
+ }
+ mFilters = filtersBuilder.build();
+ if (mChreStarted) {
+ sendFilters(mFilters);
+ mFilters = null;
+ }
+ }
+
+ private void sendFilters(Blefilter.BleFilters filters) {
+ NanoAppMessage message =
+ NanoAppMessage.createMessageToNanoApp(
+ NANOAPP_ID, NANOAPP_MESSAGE_TYPE_FILTER, filters.toByteArray());
+ if (!mChreCommunication.sendMessageToNanoApp(message)) {
+ Log.e(TAG, "Failed to send filters to CHRE.");
+ }
+ }
+
+ private class ChreCallback implements ChreCommunication.ContextHubCommsCallback {
+
+ @Override
+ public void started(boolean success) {
+ if (success) {
+ synchronized (ChreDiscoveryProvider.this) {
+ Log.i(TAG, "CHRE communication started");
+ mChreStarted = true;
+ if (mFilters != null) {
+ sendFilters(mFilters);
+ mFilters = null;
+ }
+ }
+ }
+ }
+
+ @Override
+ public void onHubReset() {
+ // TODO(b/221082271): hooked with upper level codes.
+ Log.i(TAG, "CHRE reset.");
+ }
+
+ @Override
+ public void onNanoAppRestart(long nanoAppId) {
+ // TODO(b/221082271): hooked with upper level codes.
+ Log.i(TAG, String.format("CHRE NanoApp %d restart.", nanoAppId));
+ }
+
+ @Override
+ public void onMessageFromNanoApp(NanoAppMessage message) {
+ if (message.getNanoAppId() != NANOAPP_ID) {
+ Log.e(TAG, "Received message from unknown nano app.");
+ return;
+ }
+ if (mListener == null) {
+ Log.e(TAG, "the listener is not set in ChreDiscoveryProvider.");
+ return;
+ }
+ if (message.getMessageType() == NANOAPP_MESSAGE_TYPE_FILTER_RESULT) {
+ try {
+ Blefilter.BleFilterResults results =
+ Blefilter.BleFilterResults.parseFrom(message.getMessageBody());
+ for (Blefilter.BleFilterResult filterResult : results.getResultList()) {
+ Blefilter.PublicCredential credential = filterResult.getPublicCredential();
+ PublicCredential publicCredential =
+ new PublicCredential.Builder(
+ credential.getSecretId().toByteArray(),
+ credential.getAuthenticityKey().toByteArray(),
+ credential.getPublicKey().toByteArray(),
+ credential.getEncryptedMetadata().toByteArray(),
+ credential.getEncryptedMetadataTag().toByteArray())
+ .build();
+ NearbyDeviceParcelable device =
+ new NearbyDeviceParcelable.Builder()
+ .setScanType(SCAN_TYPE_NEARBY_PRESENCE)
+ .setMedium(NearbyDevice.Medium.BLE)
+ .setTxPower(filterResult.getTxPower())
+ .setRssi(filterResult.getRssi())
+ .setAction(filterResult.getIntent())
+ .setPublicCredential(publicCredential)
+ .build();
+ mExecutor.execute(() -> mListener.onNearbyDeviceDiscovered(device));
+ }
+ } catch (InvalidProtocolBufferException e) {
+ Log.e(
+ TAG,
+ String.format("Failed to decode the filter result %s", e.toString()));
+ }
+ }
+ }
+ }
+}
diff --git a/nearby/service/java/com/android/server/nearby/provider/DiscoveryProviderController.java b/nearby/service/java/com/android/server/nearby/provider/DiscoveryProviderController.java
index 469f623..fa1a874 100644
--- a/nearby/service/java/com/android/server/nearby/provider/DiscoveryProviderController.java
+++ b/nearby/service/java/com/android/server/nearby/provider/DiscoveryProviderController.java
@@ -17,42 +17,43 @@
package com.android.server.nearby.provider;
import android.annotation.Nullable;
+import android.nearby.ScanFilter;
import android.nearby.ScanRequest;
-/**
- * Interface for controlling discovery providers.
- */
+import java.util.List;
+
+/** Interface for controlling discovery providers. */
interface DiscoveryProviderController {
/**
- * Sets the listener which can expect to receive all state updates from after this point.
- * May be invoked at any time.
+ * Sets the listener which can expect to receive all state updates from after this point. May be
+ * invoked at any time.
*/
void setListener(@Nullable AbstractDiscoveryProvider.Listener listener);
- /**
- * Returns true if in the started state.
- */
+ /** Returns true if in the started state. */
boolean isStarted();
/**
- * Starts the discovery provider. Must be invoked before any other method (except
- * {@link #setListener(AbstractDiscoveryProvider.Listener)} (Listener)}).
+ * Starts the discovery provider. Must be invoked before any other method (except {@link
+ * #setListener(AbstractDiscoveryProvider.Listener)} (Listener)}).
*/
void start();
/**
* Stops the discovery provider. No other methods may be invoked after this method (except
- * {@link #setListener(AbstractDiscoveryProvider.Listener)} (Listener)}), until {@link #start()} is called again.
+ * {@link #setListener(AbstractDiscoveryProvider.Listener)} (Listener)}), until {@link #start()}
+ * is called again.
*/
void stop();
- /**
- * Sets the desired scan mode.
- */
+ /** Sets the desired scan mode. */
void setProviderScanMode(@ScanRequest.ScanMode int scanMode);
/** Gets the controller scan mode. */
@ScanRequest.ScanMode
int getProviderScanMode();
+
+ /** Sets the scan filters. */
+ void setProviderScanFilters(List<ScanFilter> filters);
}
diff --git a/nearby/service/java/com/android/server/nearby/provider/DiscoveryProviderManager.java b/nearby/service/java/com/android/server/nearby/provider/DiscoveryProviderManager.java
index 7ff3110..af1c0b5 100644
--- a/nearby/service/java/com/android/server/nearby/provider/DiscoveryProviderManager.java
+++ b/nearby/service/java/com/android/server/nearby/provider/DiscoveryProviderManager.java
@@ -20,6 +20,7 @@
import static com.android.server.nearby.NearbyService.TAG;
+import android.annotation.Nullable;
import android.content.Context;
import android.nearby.IScanListener;
import android.nearby.NearbyDeviceParcelable;
@@ -35,20 +36,22 @@
import com.android.server.nearby.metrics.NearbyMetrics;
import com.android.server.nearby.presence.PresenceDiscoveryResult;
+import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
import java.util.stream.Collectors;
-/**
- * Manages all aspects of discovery providers.
- */
+/** Manages all aspects of discovery providers. */
public class DiscoveryProviderManager implements AbstractDiscoveryProvider.Listener {
protected final Object mLock = new Object();
private final Context mContext;
private final BleDiscoveryProvider mBleDiscoveryProvider;
+ @Nullable private final ChreDiscoveryProvider mChreDiscoveryProvider;
private @ScanRequest.ScanMode int mScanMode;
@GuardedBy("mLock")
@@ -65,18 +68,24 @@
}
if (nearbyDevice.getScanType() == SCAN_TYPE_NEARBY_PRESENCE) {
List<ScanFilter> presenceFilters =
- record.getScanRequest().getScanFilters().stream().filter(
- scanFilter -> scanFilter.getType()
- == SCAN_TYPE_NEARBY_PRESENCE).collect(
- Collectors.toList());
+ record.getScanRequest().getScanFilters().stream()
+ .filter(
+ scanFilter ->
+ 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)) {
continue;
}
}
try {
- record.getScanListener().onDiscovered(
- PrivacyFilter.filter(record.getScanRequest().getScanType(),
- nearbyDevice));
+ record.getScanListener()
+ .onDiscovered(
+ PrivacyFilter.filter(
+ record.getScanRequest().getScanType(), nearbyDevice));
NearbyMetrics.logScanDeviceDiscovered(
record.hashCode(), record.getScanRequest(), nearbyDevice);
} catch (RemoteException e) {
@@ -89,6 +98,10 @@
public DiscoveryProviderManager(Context context, Injector injector) {
mContext = context;
mBleDiscoveryProvider = new BleDiscoveryProvider(mContext, injector);
+ Executor executor = Executors.newSingleThreadExecutor();
+ mChreDiscoveryProvider =
+ new ChreDiscoveryProvider(
+ mContext, new ChreCommunication(injector, executor), executor);
mScanTypeScanListenerRecordMap = new HashMap<>();
}
@@ -96,23 +109,24 @@
* Registers the listener in the manager and starts scan according to the requested scan mode.
*/
public boolean registerScanListener(ScanRequest scanRequest, IScanListener listener) {
+ Log.i(TAG, "DiscoveryProviderManager registerScanListener");
synchronized (mLock) {
IBinder listenerBinder = listener.asBinder();
if (mScanTypeScanListenerRecordMap.containsKey(listener.asBinder())) {
- ScanRequest savedScanRequest = mScanTypeScanListenerRecordMap
- .get(listenerBinder).getScanRequest();
+ ScanRequest savedScanRequest =
+ mScanTypeScanListenerRecordMap.get(listenerBinder).getScanRequest();
if (scanRequest.equals(savedScanRequest)) {
Log.d(TAG, "Already registered the scanRequest: " + scanRequest);
return true;
}
}
+ ScanListenerRecord scanListenerRecord = new ScanListenerRecord(scanRequest, listener);
+ mScanTypeScanListenerRecordMap.put(listenerBinder, scanListenerRecord);
if (!startProviders(scanRequest)) {
return false;
}
- ScanListenerRecord scanListenerRecord = new ScanListenerRecord(scanRequest, listener);
- mScanTypeScanListenerRecordMap.put(listenerBinder, scanListenerRecord);
NearbyMetrics.logScanStarted(scanListenerRecord.hashCode(), scanRequest);
if (mScanMode < scanRequest.getScanMode()) {
mScanMode = scanRequest.getScanMode();
@@ -129,21 +143,23 @@
IBinder listenerBinder = listener.asBinder();
synchronized (mLock) {
if (!mScanTypeScanListenerRecordMap.containsKey(listenerBinder)) {
- Log.w(TAG,
+ Log.w(
+ TAG,
"Cannot unregister the scanRequest because the request is never "
+ "registered.");
return;
}
- ScanListenerRecord removedRecord = mScanTypeScanListenerRecordMap
- .remove(listenerBinder);
- NearbyMetrics.logScanStopped(
- removedRecord.hashCode(), removedRecord.getScanRequest());
+ ScanListenerRecord removedRecord =
+ mScanTypeScanListenerRecordMap.remove(listenerBinder);
+ NearbyMetrics.logScanStopped(removedRecord.hashCode(), removedRecord.getScanRequest());
if (mScanTypeScanListenerRecordMap.isEmpty()) {
stopProviders();
return;
}
+ // TODO(b/221082271): updates the scan with reduced filters.
+
// Removes current highest scan mode requested and sets the next highest scan mode.
if (removedRecord.getScanRequest().getScanMode() == mScanMode) {
@ScanRequest.ScanMode int highestScanModeRequested = ScanRequest.SCAN_MODE_NO_POWER;
@@ -166,8 +182,13 @@
// starts successfully.
private boolean startProviders(ScanRequest scanRequest) {
if (scanRequest.isBleEnabled()) {
- startBleProvider(scanRequest);
- return true;
+ if (mChreDiscoveryProvider.available()) {
+ startChreProvider();
+ return true;
+ } else {
+ startBleProvider(scanRequest);
+ return true;
+ }
}
return false;
}
@@ -181,31 +202,57 @@
}
}
+ private void startChreProvider() {
+ Log.d(TAG, "DiscoveryProviderManager starts CHRE scanning.");
+ synchronized (mLock) {
+ mChreDiscoveryProvider.getController().setListener(this);
+ List<ScanFilter> scanFilters = new ArrayList();
+ for (IBinder listenerBinder : mScanTypeScanListenerRecordMap.keySet()) {
+ ScanListenerRecord record = mScanTypeScanListenerRecordMap.get(listenerBinder);
+ List<ScanFilter> presenceFilters =
+ record.getScanRequest().getScanFilters().stream()
+ .filter(
+ scanFilter ->
+ scanFilter.getType() == SCAN_TYPE_NEARBY_PRESENCE)
+ .collect(Collectors.toList());
+ scanFilters.addAll(presenceFilters);
+ }
+ mChreDiscoveryProvider.getController().setProviderScanFilters(scanFilters);
+ mChreDiscoveryProvider.getController().setProviderScanMode(mScanMode);
+ mChreDiscoveryProvider.getController().start();
+ }
+ }
+
private void stopProviders() {
stopBleProvider();
+ stopChreProvider();
}
private void stopBleProvider() {
mBleDiscoveryProvider.getController().stop();
}
- private void invalidateProviderScanMode() {
- if (!mBleDiscoveryProvider.getController().isStarted()) {
- Log.d(TAG,
- "Skip invalidating BleDiscoveryProvider scan mode because the provider not "
- + "started.");
- return;
- }
- mBleDiscoveryProvider.getController().setProviderScanMode(mScanMode);
+ private void stopChreProvider() {
+ mChreDiscoveryProvider.getController().stop();
}
- private static boolean presenceFilterMatches(NearbyDeviceParcelable device,
- List<ScanFilter> scanFilters) {
+ private void invalidateProviderScanMode() {
+ if (mBleDiscoveryProvider.getController().isStarted()) {
+ mBleDiscoveryProvider.getController().setProviderScanMode(mScanMode);
+ } else {
+ Log.d(
+ TAG,
+ "Skip invalidating BleDiscoveryProvider scan mode because the provider not "
+ + "started.");
+ }
+ }
+
+ private static boolean presenceFilterMatches(
+ NearbyDeviceParcelable device, List<ScanFilter> scanFilters) {
if (scanFilters.isEmpty()) {
return true;
}
- PresenceDiscoveryResult discoveryResult = PresenceDiscoveryResult.fromScanData(
- device.getData(), device.getRssi());
+ PresenceDiscoveryResult discoveryResult = PresenceDiscoveryResult.fromDevice(device);
for (ScanFilter scanFilter : scanFilters) {
PresenceScanFilter presenceScanFilter = (PresenceScanFilter) scanFilter;
if (discoveryResult.matches(presenceScanFilter)) {
@@ -221,7 +268,6 @@
private final IScanListener mScanListener;
-
ScanListenerRecord(ScanRequest scanRequest, IScanListener iScanListener) {
mScanListener = iScanListener;
mScanRequest = scanRequest;
diff --git a/nearby/service/proto/src/presence/blefilter.proto b/nearby/service/proto/src/presence/blefilter.proto
index da56522..9f75d34 100644
--- a/nearby/service/proto/src/presence/blefilter.proto
+++ b/nearby/service/proto/src/presence/blefilter.proto
@@ -47,6 +47,14 @@
optional bytes metadata_encryption_key_tag = 2;
}
+message PublicCredential {
+ optional bytes secret_id = 1;
+ optional bytes authenticity_key = 2;
+ optional bytes public_key = 3;
+ optional bytes encrypted_metadata = 4;
+ optional bytes encrypted_metadata_tag = 5;
+}
+
message BleFilter {
optional uint32 id = 1; // Required, unique id of this filter.
// Maximum delay to notify the client after an event occurs.
@@ -73,8 +81,11 @@
// FilterResult is returned to host when a BLE event matches a Filter.
message BleFilterResult {
optional uint32 id = 1; // id of the matched Filter.
- // TODO(b/193756395): replace with BLE event proto.
- optional bytes raw_data = 2;
+ optional uint32 tx_power = 2;
+ optional uint32 rssi = 3;
+ optional uint32 intent = 4;
+ optional bytes bluetooth_address = 5;
+ optional PublicCredential public_credential = 6;
}
message BleFilterResults {
diff --git a/nearby/tests/cts/fastpair/src/android/nearby/cts/NearbyDeviceParcelableTest.java b/nearby/tests/cts/fastpair/src/android/nearby/cts/NearbyDeviceParcelableTest.java
index 87fc4cd..b9ab95f 100644
--- a/nearby/tests/cts/fastpair/src/android/nearby/cts/NearbyDeviceParcelableTest.java
+++ b/nearby/tests/cts/fastpair/src/android/nearby/cts/NearbyDeviceParcelableTest.java
@@ -20,6 +20,7 @@
import android.nearby.NearbyDevice;
import android.nearby.NearbyDeviceParcelable;
+import android.nearby.PublicCredential;
import android.os.Build;
import android.os.Parcel;
@@ -46,37 +47,50 @@
@Before
public void setUp() {
- mBuilder = new NearbyDeviceParcelable.Builder()
- .setName("testDevice")
- .setMedium(NearbyDevice.Medium.BLE)
- .setRssi(RSSI)
- .setTxPower(-90)
- .setFastPairModelId(FAST_PAIR_MODEL_ID)
- .setBluetoothAddress(BLUETOOTH_ADDRESS)
- .setData(SCAN_DATA);
+ mBuilder =
+ new NearbyDeviceParcelable.Builder()
+ .setName("testDevice")
+ .setMedium(NearbyDevice.Medium.BLE)
+ .setRssi(RSSI)
+ .setFastPairModelId(FAST_PAIR_MODEL_ID)
+ .setBluetoothAddress(BLUETOOTH_ADDRESS)
+ .setData(SCAN_DATA);
}
-
/** Verify toString returns expected string. */
@Test
- @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ @SdkSuppress(minSdkVersion = 33, codeName = "T")
public void testToString() {
+ PublicCredential publicCredential =
+ new PublicCredential.Builder(
+ new byte[] {1},
+ new byte[] {2},
+ new byte[] {3},
+ new byte[] {4},
+ new byte[] {5})
+ .build();
NearbyDeviceParcelable nearbyDeviceParcelable =
- mBuilder.setFastPairModelId(null).setData(null).build();
+ mBuilder.setFastPairModelId(null)
+ .setData(null)
+ .setPublicCredential(publicCredential)
+ .build();
- assertThat(nearbyDeviceParcelable.toString()).isEqualTo(
- "NearbyDeviceParcelable[name=testDevice, medium=BLE, rssi=-60, txPower=-90, "
- + "bluetoothAddress="
- + BLUETOOTH_ADDRESS + ", fastPairModelId=null, data=null]");
+ assertThat(nearbyDeviceParcelable.toString())
+ .isEqualTo(
+ "NearbyDeviceParcelable[name=testDevice, medium=BLE, txPower=0, rssi=-60,"
+ + " action=0, bluetoothAddress="
+ + BLUETOOTH_ADDRESS
+ + ", fastPairModelId=null, data=null]");
}
@Test
- @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ @SdkSuppress(minSdkVersion = 33, codeName = "T")
public void test_defaultNullFields() {
- NearbyDeviceParcelable nearbyDeviceParcelable = new NearbyDeviceParcelable.Builder()
- .setMedium(NearbyDevice.Medium.BLE)
- .setRssi(RSSI)
- .build();
+ NearbyDeviceParcelable nearbyDeviceParcelable =
+ new NearbyDeviceParcelable.Builder()
+ .setMedium(NearbyDevice.Medium.BLE)
+ .setRssi(RSSI)
+ .build();
assertThat(nearbyDeviceParcelable.getName()).isNull();
assertThat(nearbyDeviceParcelable.getFastPairModelId()).isNull();
@@ -88,15 +102,15 @@
}
@Test
- @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ @SdkSuppress(minSdkVersion = 33, codeName = "T")
public void testWriteParcel() {
- NearbyDeviceParcelable nearbyDeviceParcelable = mBuilder.build();
+ NearbyDeviceParcelable nearbyDeviceParcelable = mBuilder.build();
Parcel parcel = Parcel.obtain();
nearbyDeviceParcelable.writeToParcel(parcel, 0);
parcel.setDataPosition(0);
- NearbyDeviceParcelable actualNearbyDevice = NearbyDeviceParcelable.CREATOR.createFromParcel(
- parcel);
+ NearbyDeviceParcelable actualNearbyDevice =
+ NearbyDeviceParcelable.CREATOR.createFromParcel(parcel);
parcel.recycle();
assertThat(actualNearbyDevice.getRssi()).isEqualTo(RSSI);
@@ -106,32 +120,30 @@
}
@Test
- @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ @SdkSuppress(minSdkVersion = 33, codeName = "T")
public void testWriteParcel_nullModelId() {
- NearbyDeviceParcelable nearbyDeviceParcelable =
- mBuilder.setFastPairModelId(null).build();
+ NearbyDeviceParcelable nearbyDeviceParcelable = mBuilder.setFastPairModelId(null).build();
Parcel parcel = Parcel.obtain();
nearbyDeviceParcelable.writeToParcel(parcel, 0);
parcel.setDataPosition(0);
- NearbyDeviceParcelable actualNearbyDevice = NearbyDeviceParcelable.CREATOR.createFromParcel(
- parcel);
+ NearbyDeviceParcelable actualNearbyDevice =
+ NearbyDeviceParcelable.CREATOR.createFromParcel(parcel);
parcel.recycle();
assertThat(actualNearbyDevice.getFastPairModelId()).isNull();
}
@Test
- @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ @SdkSuppress(minSdkVersion = 33, codeName = "T")
public void testWriteParcel_nullBluetoothAddress() {
- NearbyDeviceParcelable nearbyDeviceParcelable =
- mBuilder.setBluetoothAddress(null).build();
+ NearbyDeviceParcelable nearbyDeviceParcelable = mBuilder.setBluetoothAddress(null).build();
Parcel parcel = Parcel.obtain();
nearbyDeviceParcelable.writeToParcel(parcel, 0);
parcel.setDataPosition(0);
- NearbyDeviceParcelable actualNearbyDevice = NearbyDeviceParcelable.CREATOR.createFromParcel(
- parcel);
+ NearbyDeviceParcelable actualNearbyDevice =
+ NearbyDeviceParcelable.CREATOR.createFromParcel(parcel);
parcel.recycle();
assertThat(actualNearbyDevice.getBluetoothAddress()).isNull();
diff --git a/nearby/tests/cts/fastpair/src/android/nearby/cts/PrivateCredentialTest.java b/nearby/tests/cts/fastpair/src/android/nearby/cts/PrivateCredentialTest.java
index 10b3cf2..f05f65f 100644
--- a/nearby/tests/cts/fastpair/src/android/nearby/cts/PrivateCredentialTest.java
+++ b/nearby/tests/cts/fastpair/src/android/nearby/cts/PrivateCredentialTest.java
@@ -60,7 +60,7 @@
}
@Test
- @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ @SdkSuppress(minSdkVersion = 33, codeName = "T")
public void testBuilder() {
PrivateCredential credential = mBuilder.build();
@@ -77,7 +77,7 @@
}
@Test
- @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ @SdkSuppress(minSdkVersion = 33, codeName = "T")
public void testWriteParcel() {
PrivateCredential credential = mBuilder.build();
diff --git a/nearby/tests/cts/fastpair/src/android/nearby/cts/PublicCredentialTest.java b/nearby/tests/cts/fastpair/src/android/nearby/cts/PublicCredentialTest.java
index b4a34cc..11bbacc 100644
--- a/nearby/tests/cts/fastpair/src/android/nearby/cts/PublicCredentialTest.java
+++ b/nearby/tests/cts/fastpair/src/android/nearby/cts/PublicCredentialTest.java
@@ -37,29 +37,32 @@
import java.util.Arrays;
-/**
- * Tests for {@link PresenceCredential}.
- */
+/** Tests for {@link PresenceCredential}. */
@RunWith(AndroidJUnit4.class)
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
public class PublicCredentialTest {
- private static final byte[] SECRETE_ID = new byte[]{1, 2, 3, 4};
- private static final byte[] AUTHENTICITY_KEY = new byte[]{0, 1, 1, 1};
- 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[] SECRETE_ID = new byte[] {1, 2, 3, 4};
+ private static final byte[] AUTHENTICITY_KEY = new byte[] {0, 1, 1, 1};
+ 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 String KEY = "KEY";
- private static final byte[] VALUE = new byte[]{1, 2, 3, 4, 5};
+ private static final byte[] VALUE = new byte[] {1, 2, 3, 4, 5};
private PublicCredential.Builder mBuilder;
@Before
public void setUp() {
- mBuilder = new PublicCredential.Builder(SECRETE_ID, AUTHENTICITY_KEY, PUBLIC_KEY,
- ENCRYPTED_METADATA, METADATA_ENCRYPTION_KEY_TAG)
- .addCredentialElement(new CredentialElement(KEY, VALUE))
- .setIdentityType(IDENTITY_TYPE_PRIVATE);
+ mBuilder =
+ new PublicCredential.Builder(
+ SECRETE_ID,
+ AUTHENTICITY_KEY,
+ PUBLIC_KEY,
+ ENCRYPTED_METADATA,
+ METADATA_ENCRYPTION_KEY_TAG)
+ .addCredentialElement(new CredentialElement(KEY, VALUE))
+ .setIdentityType(IDENTITY_TYPE_PRIVATE);
}
@Test
@@ -74,8 +77,11 @@
assertThat(Arrays.equals(credential.getAuthenticityKey(), AUTHENTICITY_KEY)).isTrue();
assertThat(Arrays.equals(credential.getPublicKey(), PUBLIC_KEY)).isTrue();
assertThat(Arrays.equals(credential.getEncryptedMetadata(), ENCRYPTED_METADATA)).isTrue();
- assertThat(Arrays.equals(credential.getEncryptedMetadataKeyTag(),
- METADATA_ENCRYPTION_KEY_TAG)).isTrue();
+ assertThat(
+ Arrays.equals(
+ credential.getEncryptedMetadataKeyTag(),
+ METADATA_ENCRYPTION_KEY_TAG))
+ .isTrue();
}
@Test
@@ -86,19 +92,73 @@
Parcel parcel = Parcel.obtain();
credential.writeToParcel(parcel, 0);
parcel.setDataPosition(0);
- PublicCredential credentialFromParcel = PublicCredential.CREATOR.createFromParcel(
- parcel);
+ PublicCredential credentialFromParcel = PublicCredential.CREATOR.createFromParcel(parcel);
parcel.recycle();
assertThat(credentialFromParcel.getType()).isEqualTo(CREDENTIAL_TYPE_PUBLIC);
assertThat(credentialFromParcel.getIdentityType()).isEqualTo(IDENTITY_TYPE_PRIVATE);
assertThat(Arrays.equals(credentialFromParcel.getSecretId(), SECRETE_ID)).isTrue();
- assertThat(Arrays.equals(credentialFromParcel.getAuthenticityKey(),
- AUTHENTICITY_KEY)).isTrue();
+ assertThat(Arrays.equals(credentialFromParcel.getAuthenticityKey(), AUTHENTICITY_KEY))
+ .isTrue();
assertThat(Arrays.equals(credentialFromParcel.getPublicKey(), PUBLIC_KEY)).isTrue();
- assertThat(Arrays.equals(credentialFromParcel.getEncryptedMetadata(),
- ENCRYPTED_METADATA)).isTrue();
- assertThat(Arrays.equals(credentialFromParcel.getEncryptedMetadataKeyTag(),
- METADATA_ENCRYPTION_KEY_TAG)).isTrue();
+ assertThat(Arrays.equals(credentialFromParcel.getEncryptedMetadata(), ENCRYPTED_METADATA))
+ .isTrue();
+ assertThat(
+ Arrays.equals(
+ credentialFromParcel.getEncryptedMetadataKeyTag(),
+ METADATA_ENCRYPTION_KEY_TAG))
+ .isTrue();
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testEquals() {
+ PublicCredential credentialOne =
+ new PublicCredential.Builder(
+ SECRETE_ID,
+ AUTHENTICITY_KEY,
+ PUBLIC_KEY,
+ ENCRYPTED_METADATA,
+ METADATA_ENCRYPTION_KEY_TAG)
+ .addCredentialElement(new CredentialElement(KEY, VALUE))
+ .setIdentityType(IDENTITY_TYPE_PRIVATE)
+ .build();
+
+ PublicCredential credentialTwo =
+ new PublicCredential.Builder(
+ SECRETE_ID,
+ AUTHENTICITY_KEY,
+ PUBLIC_KEY,
+ ENCRYPTED_METADATA,
+ METADATA_ENCRYPTION_KEY_TAG)
+ .addCredentialElement(new CredentialElement(KEY, VALUE))
+ .setIdentityType(IDENTITY_TYPE_PRIVATE)
+ .build();
+ assertThat(credentialOne.equals((Object) credentialTwo)).isTrue();
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testUnEquals() {
+ byte[] idOne = new byte[] {1, 2, 3, 4};
+ byte[] idTwo = new byte[] {4, 5, 6, 7};
+ PublicCredential credentialOne =
+ new PublicCredential.Builder(
+ idOne,
+ AUTHENTICITY_KEY,
+ PUBLIC_KEY,
+ ENCRYPTED_METADATA,
+ METADATA_ENCRYPTION_KEY_TAG)
+ .build();
+
+ PublicCredential credentialTwo =
+ new PublicCredential.Builder(
+ idTwo,
+ AUTHENTICITY_KEY,
+ PUBLIC_KEY,
+ ENCRYPTED_METADATA,
+ METADATA_ENCRYPTION_KEY_TAG)
+ .build();
+ assertThat(credentialOne.equals((Object) credentialTwo)).isFalse();
}
}
diff --git a/nearby/tests/multidevices/clients/src/android/nearby/multidevices/fastpair/provider/controller/FastPairProviderSimulatorController.kt b/nearby/tests/multidevices/clients/src/android/nearby/multidevices/fastpair/provider/controller/FastPairProviderSimulatorController.kt
index b591ae0..2ab6dbd 100644
--- a/nearby/tests/multidevices/clients/src/android/nearby/multidevices/fastpair/provider/controller/FastPairProviderSimulatorController.kt
+++ b/nearby/tests/multidevices/clients/src/android/nearby/multidevices/fastpair/provider/controller/FastPairProviderSimulatorController.kt
@@ -64,9 +64,6 @@
.setRemoveAllDevicesDuringPairing(true)
.build()
)
-
- // TODO(b/222070055): Workaround the FATAL EXCEPTION after the end of initial pairing.
- simulator!!.setSuppressSubsequentPairingNotification(true)
}
fun getProviderSimulatorBleAddress() = simulator!!.bleAddress!!
diff --git a/nearby/tests/unit/src/com/android/server/nearby/metrics/NearbyMetricsTest.java b/nearby/tests/unit/src/com/android/server/nearby/metrics/NearbyMetricsTest.java
index 252bb90..c4d1ee2 100644
--- a/nearby/tests/unit/src/com/android/server/nearby/metrics/NearbyMetricsTest.java
+++ b/nearby/tests/unit/src/com/android/server/nearby/metrics/NearbyMetricsTest.java
@@ -20,6 +20,7 @@
import static android.nearby.ScanRequest.SCAN_TYPE_NEARBY_SHARE;
import android.nearby.NearbyDeviceParcelable;
+import android.nearby.PublicCredential;
import android.nearby.ScanRequest;
import android.os.WorkSource;
@@ -42,39 +43,50 @@
private static final int RSSI = -60;
private static final String FAST_PAIR_MODEL_ID = "1234";
private static final String BLUETOOTH_ADDRESS = "00:11:22:33:FF:EE";
- private static final byte[] SCAN_DATA = new byte[]{1, 2, 3, 4};
+ private static final byte[] SCAN_DATA = new byte[] {1, 2, 3, 4};
+ private static final PublicCredential PUBLIC_CREDENTIAL =
+ new PublicCredential.Builder(
+ new byte[] {1},
+ new byte[] {2},
+ new byte[] {3},
+ new byte[] {4},
+ new byte[] {5})
+ .build();
private final WorkSource mWorkSource = new WorkSource(WORK_SOURCE_UID);
private final WorkSource mEmptyWorkSource = new WorkSource();
- private final ScanRequest.Builder mScanRequestBuilder = new ScanRequest.Builder()
- .setScanMode(SCAN_MODE_BALANCED)
- .setScanType(SCAN_TYPE_NEARBY_SHARE);
- private final ScanRequest mScanRequest = mScanRequestBuilder
- .setWorkSource(mWorkSource)
- .build();
- private final ScanRequest mScanRequestWithEmptyWorkSource = mScanRequestBuilder
- .setWorkSource(mEmptyWorkSource)
- .build();
+ private final ScanRequest.Builder mScanRequestBuilder =
+ new ScanRequest.Builder()
+ .setScanMode(SCAN_MODE_BALANCED)
+ .setScanType(SCAN_TYPE_NEARBY_SHARE);
+ private final ScanRequest mScanRequest = mScanRequestBuilder.setWorkSource(mWorkSource).build();
+ private final ScanRequest mScanRequestWithEmptyWorkSource =
+ mScanRequestBuilder.setWorkSource(mEmptyWorkSource).build();
private final NearbyDeviceParcelable mNearbyDevice =
new NearbyDeviceParcelable.Builder()
.setName(DEVICE_NAME)
.setMedium(SCAN_MEDIUM)
+ .setTxPower(1)
.setRssi(RSSI)
+ .setAction(1)
+ .setPublicCredential(PUBLIC_CREDENTIAL)
.setFastPairModelId(FAST_PAIR_MODEL_ID)
.setBluetoothAddress(BLUETOOTH_ADDRESS)
- .setData(SCAN_DATA).build();
+ .setData(SCAN_DATA)
+ .build();
private MockitoSession mSession;
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
- mSession = ExtendedMockito.mockitoSession()
- .strictness(Strictness.LENIENT)
- .mockStatic(NearbyStatsLog.class)
- .startMocking();
+ mSession =
+ ExtendedMockito.mockitoSession()
+ .strictness(Strictness.LENIENT)
+ .mockStatic(NearbyStatsLog.class)
+ .startMocking();
}
@After
@@ -164,8 +176,8 @@
@Test
public void testLogScanDeviceDiscovered_emptyWorkSource() {
- NearbyMetrics.logScanDeviceDiscovered(SESSION_ID, mScanRequestWithEmptyWorkSource,
- mNearbyDevice);
+ NearbyMetrics.logScanDeviceDiscovered(
+ SESSION_ID, mScanRequestWithEmptyWorkSource, mNearbyDevice);
ExtendedMockito.verify(() -> NearbyStatsLog.write(
NearbyStatsLog.NEARBY_DEVICE_SCAN_STATE_CHANGED,
-1,
diff --git a/nearby/tests/unit/src/com/android/server/nearby/presence/PresenceManagerTest.java b/nearby/tests/unit/src/com/android/server/nearby/presence/PresenceManagerTest.java
index f9676e3..d32e325 100644
--- a/nearby/tests/unit/src/com/android/server/nearby/presence/PresenceManagerTest.java
+++ b/nearby/tests/unit/src/com/android/server/nearby/presence/PresenceManagerTest.java
@@ -16,93 +16,24 @@
package com.android.server.nearby.presence;
-import static com.android.server.nearby.presence.PresenceManager.NANOAPP_ID;
-import static com.android.server.nearby.presence.PresenceManager.NANOAPP_MESSAGE_TYPE_FILTER_RESULT;
-import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-
-import android.content.Context;
-import android.hardware.location.NanoAppMessage;
import androidx.test.filters.SdkSuppress;
import org.junit.Before;
import org.junit.Test;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Captor;
-import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-import java.util.Collections;
-
-import service.proto.Blefilter;
-
public class PresenceManagerTest {
- @Mock private Context mContext;
- @Mock private PresenceManager.PresenceCallback mPresenceCallback;
- @Mock private ChreCommunication mChreCommunication;
-
- @Captor ArgumentCaptor<ChreCommunication.ContextHubCommsCallback> mChreCallbackCaptor;
- @Captor ArgumentCaptor<NanoAppMessage> mNanoAppMessageCaptor;
-
private PresenceManager mPresenceManager;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
- mPresenceManager = new PresenceManager(mContext, mPresenceCallback);
}
@Test
@SdkSuppress(minSdkVersion = 32, codeName = "T")
- public void testInit() {
- mPresenceManager.initiate(mChreCommunication);
- verify(mChreCommunication).start(any(), eq(Collections.singleton(NANOAPP_ID)));
- }
-
- @Test
- @SdkSuppress(minSdkVersion = 32, codeName = "T")
- public void testOnFilterResults() {
- Blefilter.BleFilterResults results = Blefilter.BleFilterResults.newBuilder().build();
- NanoAppMessage chre_message =
- NanoAppMessage.createMessageToNanoApp(
- NANOAPP_ID, NANOAPP_MESSAGE_TYPE_FILTER_RESULT, results.toByteArray());
- mPresenceManager.initiate(mChreCommunication);
- verify(mChreCommunication).start(mChreCallbackCaptor.capture(), any());
- mChreCallbackCaptor.getValue().onMessageFromNanoApp(chre_message);
- verify(mPresenceCallback).onFilterResults(eq(results));
- }
-
- @Test
- @SdkSuppress(minSdkVersion = 32, codeName = "T")
- public void testUpdateFiltersBeforeChreStarted() {
- Blefilter.BleFilters filters = Blefilter.BleFilters.newBuilder().build();
- mPresenceManager.updateFilters(filters);
- verify(mChreCommunication, never()).sendMessageToNanoApp(any());
- mPresenceManager.initiate(mChreCommunication);
- verify(mChreCommunication).start(mChreCallbackCaptor.capture(), any());
- mChreCallbackCaptor.getValue().started(true);
- verify(mChreCommunication, times(1)).sendMessageToNanoApp(mNanoAppMessageCaptor.capture());
- assertThat(mNanoAppMessageCaptor.getValue().getMessageBody())
- .isEqualTo(filters.toByteArray());
- }
-
- @Test
- @SdkSuppress(minSdkVersion = 32, codeName = "T")
- public void testUpdateFiltersAfterChreStarted() {
- mPresenceManager.initiate(mChreCommunication);
- verify(mChreCommunication).start(mChreCallbackCaptor.capture(), any());
- mChreCallbackCaptor.getValue().started(true);
- Blefilter.BleFilters filters = Blefilter.BleFilters.newBuilder().build();
- mPresenceManager.updateFilters(filters);
- verify(mChreCommunication, times(1)).sendMessageToNanoApp(mNanoAppMessageCaptor.capture());
- assertThat(mNanoAppMessageCaptor.getValue().getMessageBody())
- .isEqualTo(filters.toByteArray());
- }
+ public void testInit() {}
}
diff --git a/nearby/tests/unit/src/com/android/server/nearby/presence/ChreCommunicationTest.java b/nearby/tests/unit/src/com/android/server/nearby/provider/ChreCommunicationTest.java
similarity index 85%
rename from nearby/tests/unit/src/com/android/server/nearby/presence/ChreCommunicationTest.java
rename to nearby/tests/unit/src/com/android/server/nearby/provider/ChreCommunicationTest.java
index b221f46..1b29b52 100644
--- a/nearby/tests/unit/src/com/android/server/nearby/presence/ChreCommunicationTest.java
+++ b/nearby/tests/unit/src/com/android/server/nearby/provider/ChreCommunicationTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server.nearby.presence;
+package com.android.server.nearby.provider;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
@@ -65,10 +65,11 @@
when(mTransactionResponse.getContents())
.thenReturn(
Collections.singletonList(
- new NanoAppState(PresenceManager.NANOAPP_ID, 1, true)));
+ new NanoAppState(ChreDiscoveryProvider.NANOAPP_ID, 1, true)));
mChreCommunication = new ChreCommunication(mInjector, new InlineExecutor());
- mChreCommunication.start(mChreCallback, Collections.singleton(PresenceManager.NANOAPP_ID));
+ mChreCommunication.start(
+ mChreCallback, Collections.singleton(ChreDiscoveryProvider.NANOAPP_ID));
verify(mTransaction).setOnCompleteListener(mOnQueryCompleteListenerCaptor.capture(), any());
mOnQueryCompleteListenerCaptor.getValue().onComplete(mTransaction, mTransactionResponse);
@@ -89,8 +90,8 @@
public void testSendMessageToNanApp() {
NanoAppMessage message =
NanoAppMessage.createMessageToNanoApp(
- PresenceManager.NANOAPP_ID,
- PresenceManager.NANOAPP_MESSAGE_TYPE_FILTER,
+ ChreDiscoveryProvider.NANOAPP_ID,
+ ChreDiscoveryProvider.NANOAPP_MESSAGE_TYPE_FILTER,
new byte[] {1, 2, 3});
mChreCommunication.sendMessageToNanoApp(message);
verify(mClient).sendMessageToNanoApp(eq(message));
@@ -100,8 +101,8 @@
public void testOnMessageFromNanoApp() {
NanoAppMessage message =
NanoAppMessage.createMessageToNanoApp(
- PresenceManager.NANOAPP_ID,
- PresenceManager.NANOAPP_MESSAGE_TYPE_FILTER_RESULT,
+ ChreDiscoveryProvider.NANOAPP_ID,
+ ChreDiscoveryProvider.NANOAPP_MESSAGE_TYPE_FILTER_RESULT,
new byte[] {1, 2, 3});
mChreCommunication.onMessageFromNanoApp(mClient, message);
verify(mChreCallback).onMessageFromNanoApp(eq(message));
@@ -115,8 +116,8 @@
@Test
public void testOnNanoAppLoaded() {
- mChreCommunication.onNanoAppLoaded(mClient, PresenceManager.NANOAPP_ID);
- verify(mChreCallback).onNanoAppRestart(eq(PresenceManager.NANOAPP_ID));
+ mChreCommunication.onNanoAppLoaded(mClient, ChreDiscoveryProvider.NANOAPP_ID);
+ verify(mChreCallback).onNanoAppRestart(eq(ChreDiscoveryProvider.NANOAPP_ID));
}
private static class InlineExecutor implements Executor {
diff --git a/nearby/tests/unit/src/com/android/server/nearby/provider/ChreDiscoveryProviderTest.java b/nearby/tests/unit/src/com/android/server/nearby/provider/ChreDiscoveryProviderTest.java
new file mode 100644
index 0000000..7c0dd92
--- /dev/null
+++ b/nearby/tests/unit/src/com/android/server/nearby/provider/ChreDiscoveryProviderTest.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.nearby.provider;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.verify;
+
+import android.content.Context;
+import android.hardware.location.NanoAppMessage;
+import android.nearby.ScanFilter;
+
+import androidx.test.filters.SdkSuppress;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.google.protobuf.ByteString;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import service.proto.Blefilter;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Executor;
+
+public class ChreDiscoveryProviderTest {
+ @Mock AbstractDiscoveryProvider.Listener mListener;
+ @Mock ChreCommunication mChreCommunication;
+
+ @Captor ArgumentCaptor<ChreCommunication.ContextHubCommsCallback> mChreCallbackCaptor;
+
+ private ChreDiscoveryProvider mChreDiscoveryProvider;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ Context context = InstrumentationRegistry.getInstrumentation().getContext();
+ mChreDiscoveryProvider =
+ new ChreDiscoveryProvider(context, mChreCommunication, new InLineExecutor());
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testOnStart() {
+ List<ScanFilter> scanFilters = new ArrayList<>();
+ mChreDiscoveryProvider.getController().setProviderScanFilters(scanFilters);
+ mChreDiscoveryProvider.onStart();
+ verify(mChreCommunication).start(mChreCallbackCaptor.capture(), any());
+ mChreCallbackCaptor.getValue().started(true);
+ verify(mChreCommunication).sendMessageToNanoApp(any());
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testOnNearbyDeviceDiscovered() {
+ 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)
+ .setPublicCredential(credential)
+ .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.onStart();
+ verify(mChreCommunication).start(mChreCallbackCaptor.capture(), any());
+ mChreCallbackCaptor.getValue().onMessageFromNanoApp(chre_message);
+ verify(mListener).onNearbyDeviceDiscovered(any());
+ }
+
+ private static class InLineExecutor implements Executor {
+ @Override
+ public void execute(Runnable command) {
+ command.run();
+ }
+ }
+}