Merge "Update the commands to build and install the mainline module."
diff --git a/nearby/framework/java/android/nearby/BroadcastCallback.java b/nearby/framework/java/android/nearby/BroadcastCallback.java
new file mode 100644
index 0000000..54c1916
--- /dev/null
+++ b/nearby/framework/java/android/nearby/BroadcastCallback.java
@@ -0,0 +1,64 @@
+/*
+ * 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 android.nearby;
+
+import android.annotation.IntDef;
+import android.annotation.SystemApi;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Callback when broadcasting request using nearby specification.
+ *
+ * @hide
+ */
+@SystemApi
+public interface BroadcastCallback {
+ /** Broadcast was successful. */
+ int STATUS_OK = 0;
+
+ /** General status code when broadcast failed. */
+ int STATUS_FAILURE = 1;
+
+ /**
+ * Broadcast failed as the callback was already registered.
+ */
+ int STATUS_FAILURE_ALREADY_REGISTERED = 2;
+
+ /**
+ * Broadcast failed as the request contains excessive data.
+ */
+ int STATUS_FAILURE_SIZE_EXCEED_LIMIT = 3;
+
+ /**
+ * Broadcast failed as the client doesn't hold required permissions.
+ */
+ int STATUS_FAILURE_MISSING_PERMISSIONS = 4;
+
+ /** @hide **/
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({STATUS_OK, STATUS_FAILURE, STATUS_FAILURE_ALREADY_REGISTERED,
+ STATUS_FAILURE_SIZE_EXCEED_LIMIT, STATUS_FAILURE_MISSING_PERMISSIONS})
+ @interface BroadcastStatus {
+ }
+
+ /**
+ * Called when broadcast status changes.
+ */
+ void onStatus(@BroadcastStatus int status);
+}
diff --git a/nearby/framework/java/android/nearby/BroadcastRequest.java b/nearby/framework/java/android/nearby/BroadcastRequest.java
new file mode 100644
index 0000000..27468dd
--- /dev/null
+++ b/nearby/framework/java/android/nearby/BroadcastRequest.java
@@ -0,0 +1,156 @@
+/*
+ * 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 android.nearby;
+
+import android.annotation.IntDef;
+import android.annotation.IntRange;
+import android.annotation.NonNull;
+import android.annotation.SuppressLint;
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Represents a {@link BroadcastRequest}.
+ *
+ * @hide
+ */
+@SystemApi
+@SuppressLint("ParcelNotFinal") // BroadcastRequest constructor is not public
+public abstract class BroadcastRequest implements Parcelable {
+
+ /** Broadcast type for advertising using nearby presence protocol. */
+ public static final int BROADCAST_TYPE_NEARBY_PRESENCE = 3;
+
+ /** @hide **/
+ // Currently, only Nearby Presence broadcast is supported, in the future
+ // broadcasting using other nearby specifications will be added.
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({BROADCAST_TYPE_NEARBY_PRESENCE})
+ public @interface BroadcastType {
+ }
+
+ /**
+ * Tx Power when the value is not set in the broadcast.
+ */
+ public static final int UNKNOWN_TX_POWER = -100;
+
+ /**
+ * V0 of Nearby Presence Protocol.
+ */
+ public static final int PRESENCE_VERSION_V0 = 0;
+
+ /**
+ * V1 of Nearby Presence Protocol.
+ */
+ public static final int PRESENCE_VERSION_V1 = 1;
+
+ /** @hide **/
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({PRESENCE_VERSION_V0, PRESENCE_VERSION_V1})
+ public @interface BroadcastVersion {
+ }
+
+ public static final @NonNull Creator<BroadcastRequest> CREATOR =
+ new Creator<BroadcastRequest>() {
+ @Override
+ public BroadcastRequest createFromParcel(Parcel in) {
+ int type = in.readInt();
+ switch (type) {
+ case BroadcastRequest.BROADCAST_TYPE_NEARBY_PRESENCE:
+ return PresenceBroadcastRequest.createFromParcelBody(in);
+ default:
+ throw new IllegalStateException(
+ "Unexpected broadcast type (value " + type + ") in parcel.");
+ }
+ }
+
+ @Override
+ public BroadcastRequest[] newArray(int size) {
+ return new BroadcastRequest[size];
+ }
+ };
+
+ private final @BroadcastType int mType;
+ private final @BroadcastVersion int mVersion;
+ private final int mTxPower;
+ private final List<Integer> mMediums;
+
+ BroadcastRequest(@BroadcastType int type, @BroadcastVersion int version, int txPower,
+ List<Integer> mediums) {
+ this.mType = type;
+ this.mVersion = version;
+ this.mTxPower = txPower;
+ this.mMediums = mediums;
+ }
+
+ BroadcastRequest(@BroadcastType int type, Parcel in) {
+ mType = type;
+ mVersion = in.readInt();
+ mTxPower = in.readInt();
+ mMediums = new ArrayList<>();
+ in.readList(mMediums, Integer.class.getClassLoader(), Integer.class);
+ }
+
+ /**
+ * Returns the type of the broadcast.
+ */
+ public @BroadcastType int getType() {
+ return mType;
+ }
+
+ /**
+ * Returns the version of the broadcast.
+ */
+ public @BroadcastVersion int getVersion() {
+ return mVersion;
+ }
+
+ /**
+ * Returns the calibrated TX power when this request is broadcast.
+ */
+ @IntRange(from = -127, to = 126)
+ public int getTxPower() {
+ return mTxPower;
+ }
+
+ /**
+ * Returns the list of broadcast mediums.
+ */
+ @NonNull
+ public List<Integer> getMediums() {
+ return mMediums;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeInt(mType);
+ dest.writeInt(mVersion);
+ dest.writeInt(mTxPower);
+ dest.writeList(mMediums);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+}
diff --git a/nearby/framework/java/android/nearby/CredentialElement.java b/nearby/framework/java/android/nearby/CredentialElement.java
new file mode 100644
index 0000000..d2049d1
--- /dev/null
+++ b/nearby/framework/java/android/nearby/CredentialElement.java
@@ -0,0 +1,90 @@
+/*
+ * 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 android.nearby;
+
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.internal.util.Preconditions;
+
+/**
+ * Represents an element in {@link PresenceCredential}.
+ *
+ * @hide
+ */
+@SystemApi
+public final class CredentialElement implements Parcelable {
+ private final String mKey;
+ private final byte[] mValue;
+
+ /**
+ * 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");
+ mKey = key;
+ mValue = value;
+ }
+
+ @NonNull
+ public static final Parcelable.Creator<CredentialElement> CREATOR =
+ new Parcelable.Creator<CredentialElement>() {
+ @Override
+ public CredentialElement createFromParcel(Parcel in) {
+ String key = in.readString();
+ byte[] value = new byte[in.readInt()];
+ in.readByteArray(value);
+ return new CredentialElement(key, value);
+ }
+
+ @Override
+ public CredentialElement[] newArray(int size) {
+ return new CredentialElement[size];
+ }
+ };
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeString(mKey);
+ dest.writeInt(mValue.length);
+ dest.writeByteArray(mValue);
+ }
+
+ /**
+ * Returns the key of the credential element.
+ */
+ @NonNull
+ public String getKey() {
+ return mKey;
+ }
+
+ /**
+ * Returns the value of the credential element.
+ */
+ @NonNull
+ public byte[] getValue() {
+ return mValue;
+ }
+}
diff --git a/nearby/framework/java/android/nearby/DataElement.java b/nearby/framework/java/android/nearby/DataElement.java
new file mode 100644
index 0000000..6fa5fb5
--- /dev/null
+++ b/nearby/framework/java/android/nearby/DataElement.java
@@ -0,0 +1,89 @@
+/*
+ * 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 android.nearby;
+
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.internal.util.Preconditions;
+
+
+/**
+ * Represents a data element in Nearby Presence.
+ *
+ * @hide
+ */
+@SystemApi
+public final class DataElement implements Parcelable {
+
+ private final int mKey;
+ private final byte[] mValue;
+
+ /**
+ * Constructs a {@link DataElement}.
+ */
+ public DataElement(int key, @NonNull byte[] value) {
+ Preconditions.checkState(value != null, "value cannot be null");
+ mKey = key;
+ mValue = value;
+ }
+
+ @NonNull
+ public static final Creator<DataElement> CREATOR = new Creator<DataElement>() {
+ @Override
+ public DataElement createFromParcel(Parcel in) {
+ int key = in.readInt();
+ byte[] value = new byte[in.readInt()];
+ in.readByteArray(value);
+ return new DataElement(key, value);
+ }
+
+ @Override
+ public DataElement[] newArray(int size) {
+ return new DataElement[size];
+ }
+ };
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeInt(mKey);
+ dest.writeInt(mValue.length);
+ dest.writeByteArray(mValue);
+ }
+
+ /**
+ * Returns the key of the data element, as defined in the nearby presence specification.
+ */
+ public int getKey() {
+ return mKey;
+ }
+
+ /**
+ * Returns the value of the data element.
+ */
+ @NonNull
+ public byte[] getValue() {
+ return mValue;
+ }
+}
diff --git a/nearby/framework/java/android/nearby/FastPairDevice.aidl b/nearby/framework/java/android/nearby/FastPairDevice.aidl
new file mode 100644
index 0000000..5942966
--- /dev/null
+++ b/nearby/framework/java/android/nearby/FastPairDevice.aidl
@@ -0,0 +1,24 @@
+/*
+ * 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 android.nearby;
+
+/**
+ * A class represents a Fast Pair device that can be discovered by multiple mediums.
+ *
+ * {@hide}
+ */
+parcelable FastPairDevice;
diff --git a/nearby/framework/java/android/nearby/FastPairDevice.java b/nearby/framework/java/android/nearby/FastPairDevice.java
index 1e766a5..e12b4f8 100644
--- a/nearby/framework/java/android/nearby/FastPairDevice.java
+++ b/nearby/framework/java/android/nearby/FastPairDevice.java
@@ -22,7 +22,9 @@
import android.os.Parcel;
import android.os.Parcelable;
+import java.util.ArrayList;
import java.util.Arrays;
+import java.util.List;
import java.util.Objects;
/**
@@ -41,7 +43,10 @@
if (in.readInt() == 1) {
builder.setName(in.readString());
}
- builder.setMedium(in.readInt());
+ int size = in.readInt();
+ for (int i = 0; i < size; i++) {
+ builder.addMedium(in.readInt());
+ }
builder.setRssi(in.readInt());
if (in.readInt() == 1) {
builder.setModelId(in.readString());
@@ -75,7 +80,7 @@
* Creates a new FastPairDevice.
*
* @param name Name of the FastPairDevice. Can be {@code null} if there is no name.
- * @param medium The {@link Medium} over which the device is discovered.
+ * @param mediums The {@link Medium}s over which the device is discovered.
* @param rssi The received signal strength in dBm.
* @param modelId The identifier of the Fast Pair device.
* Can be {@code null} if there is no Model ID.
@@ -83,44 +88,18 @@
* @param data Extra data for a Fast Pair device.
*/
public FastPairDevice(@Nullable String name,
- @Medium int medium,
+ List<Integer> mediums,
int rssi,
@Nullable String modelId,
@NonNull String bluetoothAddress,
@Nullable byte[] data) {
- super(name, medium, rssi);
+ super(name, mediums, rssi);
this.mModelId = modelId;
this.mBluetoothAddress = bluetoothAddress;
this.mData = data;
}
/**
- * Gets the name of the device, or {@code null} if not available.
- *
- * @hide
- */
- @Nullable
- @Override
- public String getName() {
- return mName;
- }
-
- /** Gets the medium over which this device was discovered. */
- @Override
- public int getMedium() {
- return mMedium;
- }
-
- /**
- * Gets the received signal strength in dBm.
- */
- @IntRange(from = -127, to = 126)
- @Override
- public int getRssi() {
- return mRssi;
- }
-
- /**
* Gets the identifier of the Fast Pair device. Can be {@code null} if there is no Model ID.
*/
@Nullable
@@ -161,11 +140,15 @@
public String toString() {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("FastPairDevice [");
- if (mName != null && !mName.isEmpty()) {
- stringBuilder.append("name=").append(mName).append(", ");
+ String name = getName();
+ if (getName() != null && !name.isEmpty()) {
+ stringBuilder.append("name=").append(name).append(", ");
}
- stringBuilder.append("medium=").append(mediumToString(mMedium));
- stringBuilder.append(" rssi=").append(mRssi);
+ stringBuilder.append("medium={");
+ for (int medium: getMediums()) {
+ stringBuilder.append(mediumToString(medium));
+ }
+ stringBuilder.append("} rssi=").append(getRssi());
stringBuilder.append(" modelId=").append(mModelId);
stringBuilder.append(" bluetoothAddress=").append(mBluetoothAddress);
stringBuilder.append("]");
@@ -189,17 +172,23 @@
@Override
public int hashCode() {
return Objects.hash(
- mName, mMedium, mRssi, mModelId, mBluetoothAddress, Arrays.hashCode(mData));
+ getName(), getMediums(), getRssi(), mModelId, mBluetoothAddress,
+ Arrays.hashCode(mData));
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
- dest.writeInt(mName == null ? 0 : 1);
- if (mName != null) {
- dest.writeString(mName);
+ String name = getName();
+ dest.writeInt(name == null ? 0 : 1);
+ if (name != null) {
+ dest.writeString(name);
}
- dest.writeInt(mMedium);
- dest.writeInt(mRssi);
+ List<Integer> mediums = getMediums();
+ dest.writeInt(mediums.size());
+ for (int medium : mediums) {
+ dest.writeInt(medium);
+ }
+ dest.writeInt(getRssi());
dest.writeInt(mModelId == null ? 0 : 1);
if (mModelId != null) {
dest.writeString(mModelId);
@@ -218,13 +207,18 @@
* @hide
*/
public static final class Builder {
+ private final List<Integer> mMediums;
@Nullable private String mName;
- @Medium private int mMedium;
private int mRssi;
@Nullable private String mModelId;
private String mBluetoothAddress;
@Nullable private byte[] mData;
+
+ public Builder() {
+ mMediums = new ArrayList<>();
+ }
+
/**
* Sets the name of the Fast Pair device.
*
@@ -242,8 +236,8 @@
* @param medium The {@link Medium} over which the device is discovered.
*/
@NonNull
- public Builder setMedium(@Medium int medium) {
- mMedium = medium;
+ public Builder addMedium(@Medium int medium) {
+ mMediums.add(medium);
return this;
}
@@ -253,7 +247,7 @@
* @param rssi The received signal strength in dBm.
*/
@NonNull
- public Builder setRssi(int rssi) {
+ public Builder setRssi(@IntRange(from = -127, to = 126) int rssi) {
mRssi = rssi;
return this;
}
@@ -298,7 +292,7 @@
*/
@NonNull
public FastPairDevice build() {
- return new FastPairDevice(mName, mMedium, mRssi, mModelId,
+ return new FastPairDevice(mName, mMediums, mRssi, mModelId,
mBluetoothAddress, mData);
}
}
diff --git a/nearby/framework/java/android/nearby/FastPairDeviceMetadata.java b/nearby/framework/java/android/nearby/FastPairDeviceMetadata.java
index 852791f..c051eb0 100644
--- a/nearby/framework/java/android/nearby/FastPairDeviceMetadata.java
+++ b/nearby/framework/java/android/nearby/FastPairDeviceMetadata.java
@@ -82,6 +82,14 @@
}
/**
+ * Get device name.
+ */
+ @Nullable
+ public String getName() {
+ return mMetadataParcel.name;
+ }
+
+ /**
* Get true wireless image url for left bud.
*/
@Nullable
@@ -311,6 +319,7 @@
mBuilderParcel = new FastPairDeviceMetadataParcel();
mBuilderParcel.imageUrl = null;
mBuilderParcel.intentUri = null;
+ mBuilderParcel.name = null;
mBuilderParcel.bleTxPower = 0;
mBuilderParcel.triggerDistance = 0;
mBuilderParcel.image = null;
@@ -369,6 +378,18 @@
}
/**
+ * Set device name.
+ *
+ * @param name Device name.
+ * @return The builder, to facilitate chaining {@code builder.setXXX(..).setXXX(..)}.
+ */
+ @NonNull
+ public Builder setName(@Nullable String name) {
+ mBuilderParcel.name = name;
+ return this;
+ }
+
+ /**
* Set ble transmission power.
*
* @param bleTxPower Ble transmission power.
diff --git a/nearby/framework/java/android/nearby/FastPairStatusCallback.java b/nearby/framework/java/android/nearby/FastPairStatusCallback.java
new file mode 100644
index 0000000..1567828
--- /dev/null
+++ b/nearby/framework/java/android/nearby/FastPairStatusCallback.java
@@ -0,0 +1,30 @@
+/*
+ * 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 android.nearby;
+
+import android.annotation.NonNull;
+
+/**
+ * Reports the pair status for an ongoing pair with a {@link FastPairDevice}.
+ * @hide
+ */
+public interface FastPairStatusCallback {
+
+ /** Reports a pair status related metadata associated with a {@link FastPairDevice} */
+ void onPairUpdate(@NonNull FastPairDevice fastPairDevice,
+ PairStatusMetadata pairStatusMetadata);
+}
diff --git a/nearby/framework/java/android/nearby/NearbyDevice.java b/nearby/framework/java/android/nearby/NearbyDevice.java
index 790b2ed..538940c 100644
--- a/nearby/framework/java/android/nearby/NearbyDevice.java
+++ b/nearby/framework/java/android/nearby/NearbyDevice.java
@@ -18,11 +18,13 @@
import android.annotation.IntDef;
import android.annotation.IntRange;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import com.android.internal.util.Preconditions;
+import java.util.List;
import java.util.Objects;
/**
@@ -34,27 +36,29 @@
public abstract class NearbyDevice {
@Nullable
- final String mName;
+ private final String mName;
@Medium
- final int mMedium;
+ private final List<Integer> mMediums;
- final int mRssi;
+ private final int mRssi;
/**
* Creates a new NearbyDevice.
*
* @param name Local device name. Can be {@code null} if there is no name.
- * @param medium The {@link Medium} over which the device is discovered.
+ * @param mediums The {@link Medium}s over which the device is discovered.
* @param rssi The received signal strength in dBm.
* @hide
*/
- public NearbyDevice(@Nullable String name, @Medium int medium, int rssi) {
- Preconditions.checkState(isValidMedium(medium),
- "Not supported medium: " + medium
- + ", scan medium must be one of NearbyDevice#Medium.");
+ public NearbyDevice(@Nullable String name, List<Integer> mediums, int rssi) {
+ for (int medium : mediums) {
+ Preconditions.checkState(isValidMedium(medium),
+ "Not supported medium: " + medium
+ + ", scan medium must be one of NearbyDevice#Medium.");
+ }
mName = name;
- mMedium = medium;
+ mMediums = mediums;
mRssi = rssi;
}
@@ -81,8 +85,6 @@
/**
* The name of the device, or null if not available.
- *
- * @hide
*/
@Nullable
public String getName() {
@@ -90,9 +92,9 @@
}
/** The medium over which this device was discovered. */
- @Medium
- public int getMedium() {
- return mMedium;
+ @NonNull
+ @Medium public List<Integer> getMediums() {
+ return mMediums;
}
/**
@@ -110,8 +112,11 @@
if (mName != null && !mName.isEmpty()) {
stringBuilder.append("name=").append(mName).append(", ");
}
- stringBuilder.append("medium=").append(mediumToString(mMedium));
- stringBuilder.append(" rssi=").append(mRssi);
+ stringBuilder.append("medium={");
+ for (int medium : mMediums) {
+ stringBuilder.append(mediumToString(medium));
+ }
+ stringBuilder.append("} rssi=").append(mRssi);
stringBuilder.append("]");
return stringBuilder.toString();
}
@@ -121,7 +126,7 @@
if (other instanceof NearbyDevice) {
NearbyDevice otherDevice = (NearbyDevice) other;
return Objects.equals(mName, otherDevice.mName)
- && mMedium == otherDevice.mMedium
+ && mMediums == otherDevice.mMediums
&& mRssi == otherDevice.mRssi;
}
return false;
@@ -129,7 +134,7 @@
@Override
public int hashCode() {
- return Objects.hash(mName, mMedium, mRssi);
+ return Objects.hash(mName, mMediums, mRssi);
}
/**
diff --git a/nearby/framework/java/android/nearby/NearbyDeviceParcelable.java b/nearby/framework/java/android/nearby/NearbyDeviceParcelable.java
index 0f85519..3b0a776 100644
--- a/nearby/framework/java/android/nearby/NearbyDeviceParcelable.java
+++ b/nearby/framework/java/android/nearby/NearbyDeviceParcelable.java
@@ -60,6 +60,9 @@
builder.setFastPairModelId(in.readString());
}
if (in.readInt() == 1) {
+ builder.setBluetoothAddress(in.readString());
+ }
+ if (in.readInt() == 1) {
int dataLength = in.readInt();
byte[] data = new byte[dataLength];
in.readByteArray(data);
@@ -125,7 +128,7 @@
dest.writeString(mFastPairModelId);
}
dest.writeInt(mBluetoothAddress == null ? 0 : 1);
- if (mFastPairModelId != null) {
+ if (mBluetoothAddress != null) {
dest.writeString(mBluetoothAddress);
}
dest.writeInt(mData == null ? 0 : 1);
diff --git a/nearby/framework/java/android/nearby/NearbyManager.java b/nearby/framework/java/android/nearby/NearbyManager.java
index 20f9164..7fb14ef 100644
--- a/nearby/framework/java/android/nearby/NearbyManager.java
+++ b/nearby/framework/java/android/nearby/NearbyManager.java
@@ -34,8 +34,8 @@
import java.util.concurrent.Executor;
/**
- * This class provides a way to perform Nearby related operations such as scanning and connecting
- * to nearby devices.
+ * This class provides a way to perform Nearby related operations such as scanning, broadcasting
+ * and connecting to nearby devices.
*
* <p> To get a {@link NearbyManager} instance, call the
* <code>Context.getSystemService(NearbyManager.class)</code>.
@@ -67,7 +67,7 @@
if (scanType == ScanRequest.SCAN_TYPE_FAST_PAIR) {
return new FastPairDevice.Builder()
.setName(nearbyDeviceParcelable.getName())
- .setMedium(nearbyDeviceParcelable.getMedium())
+ .addMedium(nearbyDeviceParcelable.getMedium())
.setRssi(nearbyDeviceParcelable.getRssi())
.setModelId(nearbyDeviceParcelable.getFastPairModelId())
.setBluetoothAddress(nearbyDeviceParcelable.getBluetoothAddress())
@@ -139,6 +139,29 @@
}
}
+
+ /**
+ * Start broadcasting the request using nearby specification.
+ *
+ * @param broadcastRequest Request for the nearby broadcast.
+ * @param executor Executor for running the callback.
+ * @param callback Callback for notifying the client..
+ */
+ public void startBroadcast(@NonNull BroadcastRequest broadcastRequest,
+ @CallbackExecutor @NonNull Executor executor, @NonNull BroadcastCallback callback) {
+ // TODO(b/218187205): implement broadcast.
+ }
+
+ /**
+ * Stop the broadcast associated with the given callback.
+ *
+ * @param callback The callback that was used for starting the broadcast.
+ */
+ @SuppressLint("ExecutorRegistration")
+ public void stopBroadcast(@NonNull BroadcastCallback callback) {
+ // TODO(b/218187205): implement broadcast.
+ }
+
private static class ScanListenerTransport extends IScanListener.Stub {
private @ScanRequest.ScanType int mScanType;
diff --git a/nearby/framework/java/android/nearby/PairStatusMetadata.aidl b/nearby/framework/java/android/nearby/PairStatusMetadata.aidl
new file mode 100644
index 0000000..911a300
--- /dev/null
+++ b/nearby/framework/java/android/nearby/PairStatusMetadata.aidl
@@ -0,0 +1,24 @@
+/*
+ * 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 android.nearby;
+
+/**
+ * Metadata about an ongoing paring. Wraps transient data like status and progress.
+ *
+ * @hide
+ */
+parcelable PairStatusMetadata;
diff --git a/nearby/framework/java/android/nearby/PairStatusMetadata.java b/nearby/framework/java/android/nearby/PairStatusMetadata.java
new file mode 100644
index 0000000..438cd6b
--- /dev/null
+++ b/nearby/framework/java/android/nearby/PairStatusMetadata.java
@@ -0,0 +1,117 @@
+/*
+ * 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 android.nearby;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Objects;
+
+/**
+ * Metadata about an ongoing paring. Wraps transient data like status and progress.
+ *
+ * @hide
+ */
+public final class PairStatusMetadata implements Parcelable {
+
+ @Status
+ private final int mStatus;
+
+ /** The status of the pairing. */
+ @IntDef({
+ Status.UNKNOWN,
+ Status.SUCCESS,
+ Status.FAIL,
+ Status.DISMISS
+ })
+ public @interface Status {
+ int UNKNOWN = 1000;
+ int SUCCESS = 1001;
+ int FAIL = 1002;
+ int DISMISS = 1003;
+ }
+
+ /** Converts the status to readable string. */
+ public static String statusToString(@Status int status) {
+ switch (status) {
+ case Status.SUCCESS:
+ return "SUCCESS";
+ case Status.FAIL:
+ return "FAIL";
+ case Status.DISMISS:
+ return "DISMISS";
+ case Status.UNKNOWN:
+ default:
+ return "UNKNOWN";
+ }
+ }
+
+ public int getStatus() {
+ return mStatus;
+ }
+
+ @Override
+ public String toString() {
+ return "PairStatusMetadata[ status=" + statusToString(mStatus) + "]";
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (other instanceof PairStatusMetadata) {
+ return mStatus == ((PairStatusMetadata) other).mStatus;
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mStatus);
+ }
+
+ public PairStatusMetadata(@Status int status) {
+ mStatus = status;
+ }
+
+ public static final Creator<PairStatusMetadata> CREATOR = new Creator<PairStatusMetadata>() {
+ @Override
+ public PairStatusMetadata createFromParcel(Parcel in) {
+ return new PairStatusMetadata(in.readInt());
+ }
+
+ @Override
+ public PairStatusMetadata[] newArray(int size) {
+ return new PairStatusMetadata[size];
+ }
+ };
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public int getStability() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeInt(mStatus);
+ }
+}
diff --git a/nearby/framework/java/android/nearby/PresenceBroadcastRequest.java b/nearby/framework/java/android/nearby/PresenceBroadcastRequest.java
new file mode 100644
index 0000000..b4d4b55
--- /dev/null
+++ b/nearby/framework/java/android/nearby/PresenceBroadcastRequest.java
@@ -0,0 +1,216 @@
+/*
+ * 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 android.nearby;
+
+import android.annotation.IntRange;
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.internal.util.Preconditions;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * Request for Nearby Presence Broadcast.
+ *
+ * @hide
+ */
+@SystemApi
+public final class PresenceBroadcastRequest extends BroadcastRequest implements Parcelable {
+ private final byte[] mSalt;
+ private final List<Integer> mActions;
+ private final PrivateCredential mCredential;
+ private final List<DataElement> mExtendedProperties;
+
+ private PresenceBroadcastRequest(@BroadcastVersion int version, int txPower,
+ List<Integer> mediums, byte[] salt, List<Integer> actions,
+ PrivateCredential credential, List<DataElement> extendedProperties) {
+ super(BROADCAST_TYPE_NEARBY_PRESENCE, version, txPower, mediums);
+ mSalt = salt;
+ mActions = actions;
+ mCredential = credential;
+ mExtendedProperties = extendedProperties;
+ }
+
+ private PresenceBroadcastRequest(Parcel in) {
+ super(BROADCAST_TYPE_NEARBY_PRESENCE, in);
+ mSalt = new byte[in.readInt()];
+ in.readByteArray(mSalt);
+
+ mActions = new ArrayList<>();
+ in.readList(mActions, Integer.class.getClassLoader(), Integer.class);
+ mCredential = in.readParcelable(PrivateCredential.class.getClassLoader(),
+ PrivateCredential.class);
+ mExtendedProperties = new ArrayList<>();
+ in.readList(mExtendedProperties, DataElement.class.getClassLoader(), DataElement.class);
+ }
+
+ @NonNull
+ public static final Creator<PresenceBroadcastRequest> CREATOR =
+ new Creator<PresenceBroadcastRequest>() {
+ @Override
+ public PresenceBroadcastRequest createFromParcel(Parcel in) {
+ // Skip Broadcast request type - it's used by parent class.
+ in.readInt();
+ return createFromParcelBody(in);
+ }
+
+ @Override
+ public PresenceBroadcastRequest[] newArray(int size) {
+ return new PresenceBroadcastRequest[size];
+ }
+ };
+
+ static PresenceBroadcastRequest createFromParcelBody(Parcel in) {
+ return new PresenceBroadcastRequest(in);
+ }
+
+ /**
+ * Returns the salt associated with this broadcast request.
+ */
+ @NonNull
+ public byte[] getSalt() {
+ return mSalt;
+ }
+
+ /**
+ * Returns actions associated with this broadcast request.
+ */
+ @NonNull
+ public List<Integer> getActions() {
+ return mActions;
+ }
+
+ /**
+ * Returns the private credential associated with this broadcast request.
+ */
+ @NonNull
+ public PrivateCredential getCredential() {
+ return mCredential;
+ }
+
+ /**
+ * Returns extended property information associated with this broadcast request.
+ */
+ @NonNull
+ public List<DataElement> getExtendedProperties() {
+ return mExtendedProperties;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ super.writeToParcel(dest, flags);
+ dest.writeInt(mSalt.length);
+ dest.writeByteArray(mSalt);
+ dest.writeList(mActions);
+ dest.writeParcelable(mCredential, /** parcelableFlags= */0);
+ dest.writeList(mExtendedProperties);
+ }
+
+ /**
+ * Builder for {@link PresenceBroadcastRequest}.
+ */
+ public static final class Builder {
+ private final List<Integer> mMediums;
+ private final List<Integer> mActions;
+ private final List<DataElement> mExtendedProperties;
+
+ private int mVersion;
+ private int mTxPower;
+ private byte[] mSalt;
+ private PrivateCredential mCredential;
+
+ public Builder(@NonNull List<Integer> mediums, @NonNull byte[] salt) {
+ Preconditions.checkState(!mediums.isEmpty(), "mediums cannot be empty");
+ Preconditions.checkState(salt != null && salt.length > 0, "salt cannot be empty");
+
+ mVersion = PRESENCE_VERSION_V0;
+ mTxPower = UNKNOWN_TX_POWER;
+ mActions = new ArrayList<>();
+ mExtendedProperties = new ArrayList<>();
+
+ mSalt = salt;
+ mMediums = mediums;
+ }
+
+ /**
+ * Sets the version for this request.
+ */
+ @NonNull
+ public Builder setVersion(@BroadcastVersion int version) {
+ mVersion = version;
+ return this;
+ }
+
+ /**
+ * Sets the calibrated tx power level in dBm for this request. The tx power level should
+ * be between -127 dBm and 126 dBm.
+ */
+ @NonNull
+ public Builder setTxPower(@IntRange(from = -127, to = 126) int txPower) {
+ mTxPower = txPower;
+ return this;
+ }
+
+ /**
+ * Adds an action for the presence broadcast request.
+ */
+ @NonNull
+ public Builder addAction(@IntRange(from = 1, to = 255) int action) {
+ mActions.add(action);
+ return this;
+ }
+
+ /**
+ * Sets the credential associated with the presence broadcast request.
+ */
+ @NonNull
+ public Builder setCredential(@NonNull PrivateCredential credential) {
+ Objects.requireNonNull(credential);
+ mCredential = credential;
+ return this;
+ }
+
+ /**
+ * Adds an extended property for the presence broadcast request.
+ */
+ @NonNull
+ public Builder addExtendedProperty(@NonNull DataElement dataElement) {
+ Objects.requireNonNull(dataElement);
+ mExtendedProperties.add(dataElement);
+ return this;
+ }
+
+ /**
+ * Builds a {@link PresenceBroadcastRequest}.
+ */
+ @NonNull
+ public PresenceBroadcastRequest build() {
+ return new PresenceBroadcastRequest(mVersion, mTxPower, mMediums, mSalt, mActions,
+ mCredential, mExtendedProperties);
+ }
+ }
+}
diff --git a/nearby/framework/java/android/nearby/PresenceCredential.java b/nearby/framework/java/android/nearby/PresenceCredential.java
new file mode 100644
index 0000000..fae3603
--- /dev/null
+++ b/nearby/framework/java/android/nearby/PresenceCredential.java
@@ -0,0 +1,187 @@
+/*
+ * 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 android.nearby;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.SuppressLint;
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Represents a credential for Nearby Presence.
+ *
+ * @hide
+ */
+@SystemApi
+@SuppressLint("ParcelNotFinal") // PresenceCredential constructor is not public
+public abstract class PresenceCredential implements Parcelable {
+ /**
+ * Private credential type.
+ */
+ public static final int CREDENTIAL_TYPE_PRIVATE = 0;
+
+ /**
+ * Public credential type.
+ */
+ public static final int CREDENTIAL_TYPE_PUBLIC = 1;
+
+ /** @hide **/
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({CREDENTIAL_TYPE_PUBLIC, CREDENTIAL_TYPE_PRIVATE})
+ public @interface CredentialType {
+ }
+
+ /**
+ * Unknown identity type.
+ */
+ public static final int IDENTITY_TYPE_UNKNOWN = 0;
+
+ /**
+ * Private identity type.
+ */
+ public static final int IDENTITY_TYPE_PRIVATE = 1;
+ /**
+ * Provisioned identity type.
+ */
+ public static final int IDENTITY_TYPE_PROVISIONED = 2;
+ /**
+ * Trusted identity type.
+ */
+ public static final int IDENTITY_TYPE_TRUSTED = 3;
+ /**
+ * Public identity type.
+ */
+ public static final int IDENTITY_TYPE_PUBLIC = 4;
+
+ /** @hide **/
+ @Retention(RetentionPolicy.SOURCE)
+ @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;
+ private final byte[] mSecretId;
+ private final byte[] mAuthenticityKey;
+ private final List<CredentialElement> mCredentialElements;
+
+ PresenceCredential(@CredentialType int type, @IdentityType int identityType,
+ byte[] secretId, byte[] authenticityKey, List<CredentialElement> credentialElements) {
+ mType = type;
+ mIdentityType = identityType;
+ mSecretId = secretId;
+ mAuthenticityKey = authenticityKey;
+ mCredentialElements = credentialElements;
+ }
+
+ PresenceCredential(@CredentialType int type, Parcel in) {
+ mType = type;
+ mIdentityType = in.readInt();
+ mSecretId = new byte[in.readInt()];
+ in.readByteArray(mSecretId);
+ mAuthenticityKey = new byte[in.readInt()];
+ in.readByteArray(mAuthenticityKey);
+ mCredentialElements = new ArrayList<>();
+ in.readList(mCredentialElements, CredentialElement.class.getClassLoader(),
+ CredentialElement.class);
+ }
+
+
+ @NonNull
+ public static final Creator<PresenceCredential> CREATOR = new Creator<PresenceCredential>() {
+ @Override
+ public PresenceCredential createFromParcel(Parcel in) {
+ int type = in.readInt();
+ switch (type) {
+ case CREDENTIAL_TYPE_PRIVATE:
+ return PrivateCredential.createFromParcelBody(in);
+ case CREDENTIAL_TYPE_PUBLIC:
+ return PublicCredential.createFromParcelBody(in);
+ default:
+ throw new IllegalStateException(
+ "Unexpected credential type (value " + type + ") in parcel.");
+ }
+ }
+
+ @Override
+ public PresenceCredential[] newArray(int size) {
+ return new PresenceCredential[size];
+ }
+ };
+
+ /**
+ * Returns the type of the credential.
+ */
+ public @CredentialType int getType() {
+ return mType;
+ }
+
+ /**
+ * Returns the identity type of the credential.
+ */
+ public @IdentityType int getIdentityType() {
+ return mIdentityType;
+ }
+
+ /**
+ * Returns the secret id of the credential.
+ */
+ @NonNull
+ public byte[] getSecretId() {
+ return mSecretId;
+ }
+
+ /**
+ * Returns the authenticity key of the credential.
+ */
+ @NonNull
+ public byte[] getAuthenticityKey() {
+ return mAuthenticityKey;
+ }
+
+ /**
+ * Returns the elements of the credential.
+ */
+ @NonNull
+ public List<CredentialElement> getCredentialElements() {
+ return mCredentialElements;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeInt(mType);
+ dest.writeInt(mIdentityType);
+ dest.writeInt(mSecretId.length);
+ dest.writeByteArray(mSecretId);
+ dest.writeInt(mAuthenticityKey.length);
+ dest.writeByteArray(mAuthenticityKey);
+ dest.writeList(mCredentialElements);
+ }
+}
diff --git a/nearby/framework/java/android/nearby/PresenceDevice.java b/nearby/framework/java/android/nearby/PresenceDevice.java
index 61326c6..d5ea0b4 100644
--- a/nearby/framework/java/android/nearby/PresenceDevice.java
+++ b/nearby/framework/java/android/nearby/PresenceDevice.java
@@ -19,18 +19,22 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.os.Bundle;
+import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
/**
* Represents a Presence device from nearby scans.
*
* @hide
*/
+@SystemApi
public final class PresenceDevice extends NearbyDevice implements Parcelable {
/** The type of presence device. */
@@ -63,21 +67,13 @@
}
private final String mDeviceId;
+ private final byte[] mSalt;
+ private final byte[] mSecretId;
+ private final byte[] mEncryptedIdentity;
private final int mDeviceType;
private final String mDeviceImageUrl;
private final long mDiscoveryTimestampMillis;
- private final Bundle mExtendedProperties;
-
- /**
- * Gets the name of the device, or {@code null} if not available.
- *
- * @hide
- */
- @Nullable
- @Override
- public String getName() {
- return mName;
- }
+ private final List<DataElement> mExtendedProperties;
/**
* The id of the device.
@@ -89,6 +85,30 @@
return mDeviceId;
}
+ /**
+ * Returns the salt used when presence device is discovered.
+ */
+ @NonNull
+ public byte[] getSalt() {
+ return mSalt;
+ }
+
+ /**
+ * Returns the secret used when presence device is discovered.
+ */
+ @NonNull
+ public byte[] getSecretId() {
+ return mSecretId;
+ }
+
+ /**
+ * Returns the encrypted identity used when presence device is discovered.
+ */
+ @NonNull
+ public byte[] getEncryptedIdentity() {
+ return mEncryptedIdentity;
+ }
+
/** The type of the device. */
@DeviceType
public int getDeviceType() {
@@ -110,17 +130,19 @@
* The extended properties of the device.
*/
@NonNull
- public Bundle getExtendedProperties() {
+ public List<DataElement> getExtendedProperties() {
return mExtendedProperties;
}
- private PresenceDevice(String deviceName, int mMedium, int rssi, String deviceId,
- int deviceType,
+ private PresenceDevice(String deviceName, List<Integer> mMediums, int rssi, String deviceId,
+ byte[] salt, byte[] secretId, byte[] encryptedIdentity, int deviceType,
String deviceImageUrl, long discoveryTimestampMillis,
- Bundle extendedProperties) {
- // TODO (b/217462253): change medium to a set in NearbyDevice.
- super(deviceName, mMedium, rssi);
+ List<DataElement> extendedProperties) {
+ super(deviceName, mMediums, rssi);
mDeviceId = deviceId;
+ mSalt = salt;
+ mSecretId = secretId;
+ mEncryptedIdentity = encryptedIdentity;
mDeviceType = deviceType;
mDeviceImageUrl = deviceImageUrl;
mDiscoveryTimestampMillis = discoveryTimestampMillis;
@@ -129,12 +151,17 @@
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
- dest.writeInt(mName == null ? 0 : 1);
- if (mName != null) {
- dest.writeString(mName);
+ String name = getName();
+ dest.writeInt(name == null ? 0 : 1);
+ if (name != null) {
+ dest.writeString(name);
}
- dest.writeInt(mMedium);
- dest.writeInt(mRssi);
+ List<Integer> mediums = getMediums();
+ dest.writeInt(mediums.size());
+ for (int medium : mediums) {
+ dest.writeInt(medium);
+ }
+ dest.writeInt(getRssi());
dest.writeString(mDeviceId);
dest.writeInt(mDeviceType);
dest.writeInt(mDeviceImageUrl == null ? 0 : 1);
@@ -142,7 +169,10 @@
dest.writeString(mDeviceImageUrl);
}
dest.writeLong(mDiscoveryTimestampMillis);
- dest.writeBundle(mExtendedProperties);
+ dest.writeInt(mExtendedProperties.size());
+ for (DataElement dataElement : mExtendedProperties) {
+ dest.writeParcelable(dataElement, 0);
+ }
}
@Override
@@ -158,7 +188,10 @@
if (in.readInt() == 1) {
builder.setName(in.readString());
}
- builder.setMedium(in.readInt());
+ int size = in.readInt();
+ for (int i = 0; i < size; i++) {
+ builder.addMedium(in.readInt());
+ }
builder.setRssi(in.readInt());
builder.setDeviceId(in.readString());
builder.setDeviceType(in.readInt());
@@ -166,9 +199,10 @@
builder.setDeviceImageUrl(in.readString());
}
builder.setDiscoveryTimestampMillis(in.readLong());
- Bundle bundle = in.readBundle();
- for (String key : bundle.keySet()) {
- builder.addExtendedProperty(key, bundle.getCharSequence(key).toString());
+ int dataElementSize = in.readInt();
+ for (int i = 0; i < dataElementSize; i++) {
+ builder.addExtendedProperty(
+ in.readParcelable(DataElement.class.getClassLoader(), DataElement.class));
}
return builder.build();
}
@@ -181,23 +215,25 @@
/**
* Builder class for {@link PresenceDevice}.
- *
- * @hide
*/
public static final class Builder {
- private final Bundle mExtendedProperties;
+ private final List<DataElement> mExtendedProperties;
+ private final List<Integer> mMediums;
private String mName;
private int mRssi;
- private int mMedium;
private String mDeviceId;
+ private byte[] mSalt;
+ private byte[] mSecretId;
+ private byte[] mEncryptedIdentity;
private int mDeviceType;
private String mDeviceImageUrl;
private long mDiscoveryTimestampMillis;
public Builder() {
- mExtendedProperties = new Bundle();
+ mMediums = new ArrayList<>();
+ mExtendedProperties = new ArrayList<>();
mRssi = -100;
}
@@ -207,19 +243,19 @@
* @param name Name of the Presence. Can be {@code null} if there is no name.
*/
@NonNull
- public Builder setName(@android.annotation.Nullable String name) {
+ public Builder setName(@Nullable String name) {
mName = name;
return this;
}
/**
- * Sets the medium over which the Presence device is discovered.
+ * Adds the medium over which the Presence device is discovered.
*
* @param medium The {@link Medium} over which the device is discovered.
*/
@NonNull
- public Builder setMedium(@Medium int medium) {
- mMedium = medium;
+ public Builder addMedium(@Medium int medium) {
+ mMediums.add(medium);
return this;
}
@@ -241,10 +277,40 @@
*/
@NonNull
public Builder setDeviceId(@NonNull String deviceId) {
+ Objects.requireNonNull(deviceId);
mDeviceId = deviceId;
return this;
}
+ /**
+ * Sets the identifier on the discovered Presence device.
+ */
+ @NonNull
+ public Builder setSalt(@NonNull byte[] salt) {
+ Objects.requireNonNull(salt);
+ mSalt = salt;
+ return this;
+ }
+
+ /**
+ * Sets the secret id of the discovered Presence device.
+ */
+ @NonNull
+ public Builder setSecretId(@NonNull byte[] secretId) {
+ Objects.requireNonNull(secretId);
+ mSecretId = secretId;
+ return this;
+ }
+
+ /**
+ * Sets the encrypted identity of the discovered Presence device.
+ */
+ @NonNull
+ public Builder setEncryptedIdentity(@NonNull byte[] encryptedIdentity) {
+ Objects.requireNonNull(encryptedIdentity);
+ mEncryptedIdentity = encryptedIdentity;
+ return this;
+ }
/**
* Sets the type of discovered Presence device.
@@ -252,7 +318,7 @@
* @param deviceType Type of the Presence device.
*/
@NonNull
- public Builder setDeviceType(int deviceType) {
+ public Builder setDeviceType(@DeviceType int deviceType) {
mDeviceType = deviceType;
return this;
}
@@ -264,7 +330,7 @@
* @param deviceImageUrl Url of the image for the Presence device.
*/
@NonNull
- public Builder setDeviceImageUrl(@NonNull String deviceImageUrl) {
+ public Builder setDeviceImageUrl(@Nullable String deviceImageUrl) {
mDeviceImageUrl = deviceImageUrl;
return this;
}
@@ -285,12 +351,12 @@
/**
* Adds an extended property of the discovered presence device.
*
- * @param key Key of the extended property.
- * @param value Value of the extended property,
+ * @param dataElement Data element of the extended property.
*/
@NonNull
- public Builder addExtendedProperty(@NonNull String key, @NonNull String value) {
- mExtendedProperties.putCharSequence(key, value);
+ public Builder addExtendedProperty(@NonNull DataElement dataElement) {
+ Objects.requireNonNull(dataElement);
+ mExtendedProperties.add(dataElement);
return this;
}
@@ -299,7 +365,9 @@
*/
@NonNull
public PresenceDevice build() {
- return new PresenceDevice(mName, mMedium, mRssi, mDeviceId, mDeviceType,
+ return new PresenceDevice(mName, mMediums, mRssi, mDeviceId,
+ mSalt, mSecretId, mEncryptedIdentity,
+ mDeviceType,
mDeviceImageUrl,
mDiscoveryTimestampMillis, mExtendedProperties);
}
diff --git a/nearby/framework/java/android/nearby/PresenceScanFilter.java b/nearby/framework/java/android/nearby/PresenceScanFilter.java
index 61e5049..f0c3c06 100644
--- a/nearby/framework/java/android/nearby/PresenceScanFilter.java
+++ b/nearby/framework/java/android/nearby/PresenceScanFilter.java
@@ -16,9 +16,9 @@
package android.nearby;
+import android.annotation.IntRange;
import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.os.Bundle;
+import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.ArraySet;
@@ -27,6 +27,7 @@
import java.util.ArrayList;
import java.util.List;
+import java.util.Objects;
import java.util.Set;
/**
@@ -34,27 +35,19 @@
*
* @hide
*/
+@SystemApi
public final class PresenceScanFilter extends ScanFilter implements Parcelable {
- private final List<byte[]> mCertificates;
- private final List<Integer> mPresenceIdentities;
+ private final List<PublicCredential> mCredentials;
private final List<Integer> mPresenceActions;
- private final Bundle mExtendedProperties;
+ private final List<DataElement> mExtendedProperties;
/**
- * A list of certificates to filter on.
+ * A list of credentials to filter on.
*/
@NonNull
- public List<byte[]> getCertificates() {
- return mCertificates;
- }
-
- /**
- * A list of presence identities for matching.
- */
- @NonNull
- public List<Integer> getPresenceIdentities() {
- return mPresenceIdentities;
+ public List<PublicCredential> getCredentials() {
+ return mCredentials;
}
/**
@@ -69,42 +62,33 @@
* A bundle of extended properties for matching.
*/
@NonNull
- public Bundle getExtendedProperties() {
+ public List<DataElement> getExtendedProperties() {
return mExtendedProperties;
}
- private PresenceScanFilter(int rssiThreshold, List<byte[]> certificates,
- List<Integer> presenceIdentities, List<Integer> presenceActions,
- Bundle extendedProperties) {
+ private PresenceScanFilter(int rssiThreshold, List<PublicCredential> credentials,
+ List<Integer> presenceActions, List<DataElement> extendedProperties) {
super(ScanRequest.SCAN_TYPE_NEARBY_PRESENCE, rssiThreshold);
- mCertificates = new ArrayList<>(certificates);
- mPresenceIdentities = new ArrayList<>(presenceIdentities);
+ mCredentials = new ArrayList<>(credentials);
mPresenceActions = new ArrayList<>(presenceActions);
mExtendedProperties = extendedProperties;
}
private PresenceScanFilter(Parcel in) {
super(ScanRequest.SCAN_TYPE_NEARBY_PRESENCE, in);
- mCertificates = new ArrayList<>();
- int size = in.readInt();
- for (int i = 0; i < size; i++) {
- int len = in.readInt();
- byte[] certificate = new byte[len];
- in.readByteArray(certificate);
- mCertificates.add(certificate);
- }
- mPresenceIdentities = new ArrayList<>();
+ mCredentials = new ArrayList<>();
if (in.readInt() != 0) {
- in.readList(mPresenceIdentities, Integer.class.getClassLoader(), Integer.class);
+ in.readParcelableList(mCredentials, PublicCredential.class.getClassLoader(),
+ PublicCredential.class);
}
mPresenceActions = new ArrayList<>();
if (in.readInt() != 0) {
in.readList(mPresenceActions, Integer.class.getClassLoader(), Integer.class);
}
- mExtendedProperties = new Bundle();
- Bundle bundle = in.readBundle(getClass().getClassLoader());
- for (String key : bundle.keySet()) {
- mExtendedProperties.putString(key, bundle.getString(key));
+ mExtendedProperties = new ArrayList<>();
+ if (in.readInt() != 0) {
+ in.readParcelableList(mExtendedProperties, DataElement.class.getClassLoader(),
+ DataElement.class);
}
}
@@ -138,75 +122,66 @@
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
super.writeToParcel(dest, flags);
- dest.writeInt(mCertificates.size());
- for (byte[] certificate : mCertificates) {
- dest.writeInt(certificate.length);
- dest.writeByteArray(certificate);
- }
- dest.writeInt(mPresenceIdentities.size());
- if (!mPresenceIdentities.isEmpty()) {
- dest.writeList(mPresenceIdentities);
+ dest.writeInt(mCredentials.size());
+ if (!mCredentials.isEmpty()) {
+ dest.writeParcelableList(mCredentials, 0);
}
dest.writeInt(mPresenceActions.size());
if (!mPresenceActions.isEmpty()) {
dest.writeList(mPresenceActions);
}
- dest.writeBundle(mExtendedProperties);
+ dest.writeInt(mExtendedProperties.size());
+ if (!mExtendedProperties.isEmpty()) {
+ dest.writeList(mExtendedProperties);
+ }
}
/**
* Builder for {@link PresenceScanFilter}.
- *
- * @hide
*/
public static final class Builder {
- private int mRssiThreshold;
- private final Set<byte[]> mCertificates;
+ private int mMaxPathLoss;
+ private final Set<PublicCredential> mCredentials;
private final Set<Integer> mPresenceIdentities;
private final Set<Integer> mPresenceActions;
- private final Bundle mExtendedProperties;
+ private final List<DataElement> mExtendedProperties;
public Builder() {
- mRssiThreshold = -100;
- mCertificates = new ArraySet<>();
+ mMaxPathLoss = 127;
+ mCredentials = new ArraySet<>();
mPresenceIdentities = new ArraySet<>();
mPresenceActions = new ArraySet<>();
- mExtendedProperties = new Bundle();
+ mExtendedProperties = new ArrayList<>();
}
/**
- * Sets the rssi threshold for the scan request.
+ * Sets the max path loss (in dBm) for the scan request. The path loss is the attenuation
+ * of radio energy between sender and receiver. Path loss here is defined as (TxPower -
+ * Rssi).
*/
@NonNull
- public Builder setRssiThreshold(int rssiThreshold) {
- mRssiThreshold = rssiThreshold;
+ public Builder setMaxPathLoss(@IntRange(from = 0, to = 127) int maxPathLoss) {
+ mMaxPathLoss = maxPathLoss;
return this;
}
/**
- * Adds a list of certificates the scan filter is expected to match.
+ * Adds a credential the scan filter is expected to match.
*/
@NonNull
- public Builder addCertificate(@NonNull byte[] certificate) {
- mCertificates.add(certificate);
+ public Builder addCredential(@NonNull PublicCredential credential) {
+ Objects.requireNonNull(credential);
+ mCredentials.add(credential);
return this;
}
/**
- * Adds a presence identity for filtering.
+ * Adds a presence action for filtering, which is an action the discoverer could take
+ * when it receives the broadcast of a presence device.
*/
@NonNull
- public Builder addPresenceIdentity(int identity) {
- mPresenceIdentities.add(identity);
- return this;
- }
-
- /**
- * Adds a presence action for filtering.
- */
- @NonNull
- public Builder addPresenceAction(int action) {
+ public Builder addPresenceAction(@IntRange(from = 1, to = 255) int action) {
mPresenceActions.add(action);
return this;
}
@@ -215,8 +190,9 @@
* Add an extended property for scan filtering.
*/
@NonNull
- public Builder addExtendedProperty(@NonNull String key, @Nullable String value) {
- mExtendedProperties.putCharSequence(key, value);
+ public Builder addExtendedProperty(@NonNull DataElement dataElement) {
+ Objects.requireNonNull(dataElement);
+ mExtendedProperties.add(dataElement);
return this;
}
@@ -225,9 +201,9 @@
*/
@NonNull
public PresenceScanFilter build() {
- Preconditions.checkState(!mCertificates.isEmpty(), "certificates cannot be empty");
- return new PresenceScanFilter(mRssiThreshold, new ArrayList<>(mCertificates),
- new ArrayList<>(mPresenceIdentities),
+ Preconditions.checkState(!mCredentials.isEmpty(), "credentials cannot be empty");
+ return new PresenceScanFilter(mMaxPathLoss,
+ new ArrayList<>(mCredentials),
new ArrayList<>(mPresenceActions),
mExtendedProperties);
}
diff --git a/nearby/framework/java/android/nearby/PrivateCredential.java b/nearby/framework/java/android/nearby/PrivateCredential.java
new file mode 100644
index 0000000..8db49fa
--- /dev/null
+++ b/nearby/framework/java/android/nearby/PrivateCredential.java
@@ -0,0 +1,171 @@
+/*
+ * 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 android.nearby;
+
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.internal.util.Preconditions;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Represents a private credential.
+ *
+ * @hide
+ */
+@SystemApi
+public final class PrivateCredential extends PresenceCredential implements Parcelable {
+
+ @NonNull
+ public static final Creator<PrivateCredential> CREATOR = new Creator<PrivateCredential>() {
+ @Override
+ public PrivateCredential createFromParcel(Parcel in) {
+ in.readInt(); // Skip the type as it's used by parent class only.
+ return createFromParcelBody(in);
+ }
+
+ @Override
+ public PrivateCredential[] newArray(int size) {
+ return new PrivateCredential[size];
+ }
+ };
+
+ private byte[] mMetadataEncryptionKey;
+ private String mDeviceName;
+
+ private PrivateCredential(Parcel in) {
+ super(CREDENTIAL_TYPE_PRIVATE, in);
+ mMetadataEncryptionKey = new byte[in.readInt()];
+ in.readByteArray(mMetadataEncryptionKey);
+ mDeviceName = in.readString();
+ }
+
+ private PrivateCredential(int identityType, byte[] secretId,
+ String deviceName, byte[] authenticityKey, List<CredentialElement> credentialElements,
+ byte[] metadataEncryptionKey) {
+ super(CREDENTIAL_TYPE_PRIVATE, identityType, secretId, authenticityKey,
+ credentialElements);
+ mDeviceName = deviceName;
+ mMetadataEncryptionKey = metadataEncryptionKey;
+ }
+
+ static PrivateCredential createFromParcelBody(Parcel in) {
+ return new PrivateCredential(in);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ super.writeToParcel(dest, flags);
+ dest.writeInt(mMetadataEncryptionKey.length);
+ dest.writeByteArray(mMetadataEncryptionKey);
+ dest.writeString(mDeviceName);
+ }
+
+ /**
+ * Returns the metadata encryption key associated with this credential.
+ */
+ @NonNull
+ public byte[] getMetadataEncryptionKey() {
+ return mMetadataEncryptionKey;
+ }
+
+ /**
+ * Returns the device name associated with this credential.
+ */
+ @NonNull
+ public String getDeviceName() {
+ return mDeviceName;
+ }
+
+ /**
+ * Builder class for {@link PresenceCredential}.
+ */
+ public static final class Builder {
+ private final List<CredentialElement> mCredentialElements;
+
+ private @IdentityType int mIdentityType;
+ private byte[] mSecretId;
+ private byte[] mAuthenticityKey;
+ private byte[] mMetadataEncryptionKey;
+ private String mDeviceName;
+
+ public Builder(@NonNull byte[] secretId, @NonNull byte[] authenticityKey) {
+ Preconditions.checkState(secretId != null && secretId.length > 0,
+ "secret id cannot be empty");
+ Preconditions.checkState(authenticityKey != null && authenticityKey.length > 0,
+ "authenticity key cannot be empty");
+ mSecretId = secretId;
+ mAuthenticityKey = authenticityKey;
+ mCredentialElements = new ArrayList<>();
+ }
+
+ /**
+ * Sets the identity type for the presence credential.
+ */
+ @NonNull
+ public Builder setIdentityType(@IdentityType int identityType) {
+ mIdentityType = identityType;
+ return this;
+ }
+
+ /**
+ * Sets the metadata encryption key to the credential.
+ */
+ @NonNull
+ public Builder setMetadataEncryptionKey(@NonNull byte[] metadataEncryptionKey) {
+ mMetadataEncryptionKey = metadataEncryptionKey;
+ return this;
+ }
+
+ /**
+ * Sets the device name of the credential.
+ */
+ @NonNull
+ public Builder setDeviceName(@NonNull String deviceName) {
+ mDeviceName = deviceName;
+ return this;
+ }
+
+ /**
+ * Adds an element to the credential.
+ */
+ @NonNull
+ public Builder addCredentialElement(@NonNull CredentialElement credentialElement) {
+ mCredentialElements.add(credentialElement);
+ return this;
+ }
+
+ /**
+ * Builds the {@link PresenceCredential}.
+ */
+ @NonNull
+ public PrivateCredential build() {
+ return new PrivateCredential(mIdentityType, mSecretId, mDeviceName,
+ mAuthenticityKey, mCredentialElements, mMetadataEncryptionKey);
+ }
+
+ }
+}
diff --git a/nearby/framework/java/android/nearby/PublicCredential.java b/nearby/framework/java/android/nearby/PublicCredential.java
new file mode 100644
index 0000000..715e7fd
--- /dev/null
+++ b/nearby/framework/java/android/nearby/PublicCredential.java
@@ -0,0 +1,196 @@
+/*
+ * 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 android.nearby;
+
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * Represents a public credential.
+ *
+ * @hide
+ */
+@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);
+ }
+
+ @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,
+ byte[] metadataEncryptionKeyTag) {
+ super(CREDENTIAL_TYPE_PUBLIC, identityType, secretId, authenticityKey, credentialElements);
+ mPublicKey = publicKey;
+ mEncryptedMetadata = encryptedMetadata;
+ mEncryptedMetadataKeyTag = metadataEncryptionKeyTag;
+ }
+
+ private PublicCredential(Parcel in) {
+ super(CREDENTIAL_TYPE_PUBLIC, in);
+ mPublicKey = new byte[in.readInt()];
+ in.readByteArray(mPublicKey);
+ mEncryptedMetadata = new byte[in.readInt()];
+ in.readByteArray(mEncryptedMetadata);
+ mEncryptedMetadataKeyTag = new byte[in.readInt()];
+ in.readByteArray(mEncryptedMetadataKeyTag);
+ }
+
+ static PublicCredential createFromParcelBody(Parcel in) {
+ return new PublicCredential(in);
+ }
+
+ /**
+ * Returns the public key associated with this credential.
+ */
+ @NonNull
+ public byte[] getPublicKey() {
+ return mPublicKey;
+ }
+
+ /**
+ * Returns the encrypted metadata associated with this credential.
+ */
+ @NonNull
+ public byte[] getEncryptedMetadata() {
+ return mEncryptedMetadata;
+ }
+
+ /**
+ * Returns the metadata encryption key tag associated with this credential.
+ */
+ @NonNull
+ public byte[] getEncryptedMetadataKeyTag() {
+ return mEncryptedMetadataKeyTag;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ super.writeToParcel(dest, flags);
+ dest.writeInt(mPublicKey.length);
+ dest.writeByteArray(mPublicKey);
+ dest.writeInt(mEncryptedMetadata.length);
+ dest.writeByteArray(mEncryptedMetadata);
+ dest.writeInt(mEncryptedMetadataKeyTag.length);
+ dest.writeByteArray(mEncryptedMetadataKeyTag);
+ }
+
+ /**
+ * Builder class for {@link PresenceCredential}.
+ */
+ public static final class Builder {
+ private final List<CredentialElement> mCredentialElements;
+
+ private @IdentityType int mIdentityType;
+ private byte[] mSecretId;
+ private byte[] mAuthenticityKey;
+ private byte[] mPublicKey;
+ private byte[] mEncryptedMetadata;
+ private byte[] mEncryptedMetadataKeyTag;
+
+ public Builder(@NonNull byte[] secretId, @NonNull byte[] authenticityKey) {
+ Objects.requireNonNull(secretId);
+ Objects.requireNonNull(authenticityKey);
+ mSecretId = secretId;
+ mAuthenticityKey = authenticityKey;
+ mCredentialElements = new ArrayList<>();
+ }
+
+ /**
+ * 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.
+ */
+ @NonNull
+ public Builder addCredentialElement(@NonNull CredentialElement credentialElement) {
+ Objects.requireNonNull(credentialElement);
+ mCredentialElements.add(credentialElement);
+ return this;
+ }
+
+ /**
+ * Sets the public key for the credential.
+ */
+ @NonNull
+ public Builder setPublicKey(@NonNull byte[] publicKey) {
+ Objects.requireNonNull(publicKey);
+ mPublicKey = publicKey;
+ return this;
+ }
+
+ /**
+ * Sets the encrypted metadata.
+ */
+ @NonNull
+ public Builder setEncryptedMetadata(@NonNull byte[] encryptedMetadata) {
+ Objects.requireNonNull(encryptedMetadata);
+ mEncryptedMetadata = encryptedMetadata;
+ return this;
+ }
+
+ /**
+ * Sets the encrypted metadata key tag.
+ */
+ @NonNull
+ public Builder setEncryptedMetadataKeyTag(@NonNull byte[] encryptedMetadataKeyTag) {
+ Objects.requireNonNull(encryptedMetadataKeyTag);
+ mEncryptedMetadataKeyTag = encryptedMetadataKeyTag;
+ return this;
+ }
+
+ /**
+ * Builds the {@link PresenceCredential}.
+ */
+ @NonNull
+ public PublicCredential build() {
+ return new PublicCredential(mIdentityType, mSecretId, mAuthenticityKey,
+ mCredentialElements, mPublicKey, mEncryptedMetadata, mEncryptedMetadataKeyTag);
+ }
+
+ }
+}
diff --git a/nearby/framework/java/android/nearby/ScanFilter.java b/nearby/framework/java/android/nearby/ScanFilter.java
index 0b2a754..e16c6a0 100644
--- a/nearby/framework/java/android/nearby/ScanFilter.java
+++ b/nearby/framework/java/android/nearby/ScanFilter.java
@@ -16,8 +16,10 @@
package android.nearby;
+import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.SuppressLint;
+import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
@@ -26,6 +28,7 @@
*
* @hide
*/
+@SystemApi
@SuppressLint("ParcelNotFinal") // ScanFilter constructor is not public
public abstract class ScanFilter implements Parcelable {
public static final @NonNull Creator<ScanFilter> CREATOR = new Creator<ScanFilter>() {
@@ -33,6 +36,8 @@
public ScanFilter createFromParcel(Parcel in) {
int type = in.readInt();
switch (type) {
+ // Currently, only Nearby Presence filtering is supported, in the future
+ // filtering other nearby specifications will be added.
case ScanRequest.SCAN_TYPE_NEARBY_PRESENCE:
return PresenceScanFilter.createFromParcelBody(in);
default:
@@ -48,16 +53,16 @@
};
private final @ScanRequest.ScanType int mType;
- private final int mRssiThreshold;
+ private final int mMaxPathLoss;
/**
* Constructs a Scan Filter.
*
* @hide
*/
- ScanFilter(@ScanRequest.ScanType int type, int rssiThreshold) {
+ ScanFilter(@ScanRequest.ScanType int type, @IntRange(from = 0, to = 127) int maxPathLoss) {
mType = type;
- mRssiThreshold = rssiThreshold;
+ mMaxPathLoss = maxPathLoss;
}
/**
@@ -67,7 +72,7 @@
*/
ScanFilter(@ScanRequest.ScanType int type, Parcel in) {
mType = type;
- mRssiThreshold = in.readInt();
+ mMaxPathLoss = in.readInt();
}
/**
@@ -78,16 +83,19 @@
}
/**
- * Minimum RSSI of the received scan result.
+ * Returns the maximum path loss (in dBm) of the received scan result. The path loss is the
+ * attenuation of radio energy between sender and receiver. Path loss here is defined as
+ * (TxPower - Rssi).
*/
- public int getRssiThreshold() {
- return mRssiThreshold;
+ @IntRange(from = 0, to = 127)
+ public int getMaxPathLoss() {
+ return mMaxPathLoss;
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeInt(mType);
- dest.writeInt(mRssiThreshold);
+ dest.writeInt(mMaxPathLoss);
}
/**
@@ -97,5 +105,4 @@
public int describeContents() {
return 0;
}
-
}
diff --git a/nearby/framework/java/android/nearby/ScanRequest.java b/nearby/framework/java/android/nearby/ScanRequest.java
index 9180d5e..7ff0631 100644
--- a/nearby/framework/java/android/nearby/ScanRequest.java
+++ b/nearby/framework/java/android/nearby/ScanRequest.java
@@ -126,7 +126,7 @@
/**
* Returns true if an integer is a defined scan type.
*/
- public static boolean isValidScanType(int scanType) {
+ public static boolean isValidScanType(@ScanType int scanType) {
return scanType == SCAN_TYPE_FAST_PAIR
|| scanType == SCAN_TYPE_NEARBY_SHARE
|| scanType == SCAN_TYPE_NEARBY_PRESENCE
@@ -136,7 +136,7 @@
/**
* Returns true if an integer is a defined scan mode.
*/
- public static boolean isValidScanMode(int scanMode) {
+ public static boolean isValidScanMode(@ScanMode int scanMode) {
return scanMode == SCAN_MODE_LOW_LATENCY
|| scanMode == SCAN_MODE_BALANCED
|| scanMode == SCAN_MODE_LOW_POWER
@@ -166,8 +166,6 @@
/**
* Returns Scan Filters for this request.
- *
- * @hide
*/
@NonNull
public List<ScanFilter> getScanFilters() {
@@ -334,11 +332,10 @@
* usage of Nearby scans.
*
* @param scanFilter Filter for scanning the request.
- *
- * @hide
*/
@NonNull
public Builder addScanFilter(@NonNull ScanFilter scanFilter) {
+ Objects.requireNonNull(scanFilter);
mScanFilters.add(scanFilter);
return this;
}
diff --git a/nearby/framework/java/android/nearby/aidl/FastPairDeviceMetadataParcel.aidl b/nearby/framework/java/android/nearby/aidl/FastPairDeviceMetadataParcel.aidl
index 565439b..ef00321 100644
--- a/nearby/framework/java/android/nearby/aidl/FastPairDeviceMetadataParcel.aidl
+++ b/nearby/framework/java/android/nearby/aidl/FastPairDeviceMetadataParcel.aidl
@@ -39,6 +39,9 @@
// The image icon that shows in the notification.
byte[] image;
+ // The name of the device.
+ String name;
+
int deviceType;
// The image urls for device with device type "true wireless".
diff --git a/nearby/framework/java/android/nearby/aidl/IFastPairClient.aidl b/nearby/framework/java/android/nearby/aidl/IFastPairClient.aidl
new file mode 100644
index 0000000..4f666bc
--- /dev/null
+++ b/nearby/framework/java/android/nearby/aidl/IFastPairClient.aidl
@@ -0,0 +1,35 @@
+/*
+ * 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 android.nearby.aidl;
+
+import android.nearby.aidl.IFastPairStatusCallback;
+import android.nearby.FastPairDevice;
+
+/**
+ * 0p API for controlling Fast Pair. Used to talk between foreground activities
+ * and background services.
+ *
+ * {@hide}
+ */
+interface IFastPairClient {
+
+ void registerHalfSheet(in IFastPairStatusCallback fastPairStatusCallback);
+
+ void unregisterHalfSheet(in IFastPairStatusCallback fastPairStatusCallback);
+
+ void connect(in FastPairDevice fastPairDevice);
+}
\ No newline at end of file
diff --git a/nearby/framework/java/android/nearby/aidl/IFastPairStatusCallback.aidl b/nearby/framework/java/android/nearby/aidl/IFastPairStatusCallback.aidl
new file mode 100644
index 0000000..d844c06
--- /dev/null
+++ b/nearby/framework/java/android/nearby/aidl/IFastPairStatusCallback.aidl
@@ -0,0 +1,32 @@
+/*
+ * 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 android.nearby.aidl;
+
+import android.nearby.FastPairDevice;
+import android.nearby.PairStatusMetadata;
+
+/**
+ *
+ * Provides callbacks for Fast Pair foreground activity to learn about paring status from backend.
+ *
+ * {@hide}
+ */
+interface IFastPairStatusCallback {
+
+ /** Reports a pair status related metadata associated with a {@link FastPairDevice} */
+ void onPairUpdate(in FastPairDevice fastPairDevice, in PairStatusMetadata pairStatusMetadata);
+}
diff --git a/nearby/halfsheet/AndroidManifest.xml b/nearby/halfsheet/AndroidManifest.xml
index 3df7970..22987fb 100644
--- a/nearby/halfsheet/AndroidManifest.xml
+++ b/nearby/halfsheet/AndroidManifest.xml
@@ -20,6 +20,7 @@
<activity
android:name="com.android.nearby.halfsheet.HalfSheetActivity"
android:exported="true"
+ android:launchMode="singleInstance"
android:theme="@style/HalfSheetStyle" >
<intent-filter>
<action android:name="android.nearby.SHOW_HALFSHEET"/>
diff --git a/nearby/service/Android.bp b/nearby/service/Android.bp
index 1e1af20..8f6a227 100644
--- a/nearby/service/Android.bp
+++ b/nearby/service/Android.bp
@@ -20,6 +20,7 @@
name: "nearby-service-srcs",
srcs: [
"java/**/*.java",
+ ":statslog-nearby-java-gen",
],
}
@@ -53,6 +54,7 @@
"framework-bluetooth.stubs.module_lib", // TODO(b/215722418): Change to framework-bluetooth once fixed
"error_prone_annotations",
"framework-connectivity-tiramisu.impl",
+ "framework-statsd.stubs.module_lib",
],
static_libs: [
"androidx.annotation_annotation",
@@ -84,3 +86,12 @@
"com.android.tethering",
],
}
+
+genrule {
+ name: "statslog-nearby-java-gen",
+ tools: ["stats-log-api-gen"],
+ cmd: "$(location stats-log-api-gen) --java $(out) --module nearby " +
+ " --javaPackage com.android.server.nearby.proto --javaClass NearbyStatsLog" +
+ " --minApiLevel 33",
+ out: ["com/android/server/nearby/proto/NearbyStatsLog.java"],
+}
diff --git a/nearby/service/java/com/android/server/nearby/fastpair/Constant.java b/nearby/service/java/com/android/server/nearby/fastpair/Constant.java
index 1477d95..5958007 100644
--- a/nearby/service/java/com/android/server/nearby/fastpair/Constant.java
+++ b/nearby/service/java/com/android/server/nearby/fastpair/Constant.java
@@ -20,6 +20,17 @@
* String constant for half sheet.
*/
public class Constant {
+
+ /**
+ * Value represents true for {@link android.provider.Settings.Secure}
+ */
+ public static final int SETTINGS_TRUE_VALUE = 1;
+
+ /**
+ * Tag for Fast Pair service related logs.
+ */
+ public static final String TAG = "FastPairService";
+
public static final String EXTRA_BINDER = "com.android.server.nearby.fastpair.BINDER";
public static final String EXTRA_BUNDLE = "com.android.server.nearby.fastpair.BUNDLE_EXTRA";
public static final String SUCCESS_STATE = "SUCCESS";
diff --git a/nearby/service/java/com/android/server/nearby/fastpair/FastPairAdvHandler.java b/nearby/service/java/com/android/server/nearby/fastpair/FastPairAdvHandler.java
index 672d785..f8d5a62 100644
--- a/nearby/service/java/com/android/server/nearby/fastpair/FastPairAdvHandler.java
+++ b/nearby/service/java/com/android/server/nearby/fastpair/FastPairAdvHandler.java
@@ -30,14 +30,12 @@
import com.android.server.nearby.common.locator.Locator;
import com.android.server.nearby.fastpair.halfsheet.FastPairHalfSheetManager;
import com.android.server.nearby.provider.FastPairDataProvider;
+import com.android.server.nearby.util.DataUtils;
import com.android.server.nearby.util.FastPairDecoder;
import com.android.server.nearby.util.Hex;
-import com.google.protobuf.ByteString;
-
import java.util.List;
-import service.proto.Cache;
import service.proto.Data;
import service.proto.Rpcs;
@@ -70,36 +68,37 @@
*/
public void handleBroadcast(NearbyDevice device) {
FastPairDevice fastPairDevice = (FastPairDevice) device;
- if (mBleAddress != null && mBleAddress.equals(fastPairDevice.getBluetoothAddress())) {
- return;
- }
mBleAddress = fastPairDevice.getBluetoothAddress();
if (FastPairDecoder.checkModelId(fastPairDevice.getData())) {
byte[] model = FastPairDecoder.getModelId(fastPairDevice.getData());
Log.d("FastPairService",
- "On discovery model id" + Hex.bytesToStringLowercase(model));
+ "On discovery model id " + Hex.bytesToStringLowercase(model));
// Use api to get anti spoofing key from model id.
try {
Rpcs.GetObservedDeviceResponse response =
FastPairDataProvider.getInstance()
.loadFastPairAntispoofkeyDeviceMetadata(model);
- ByteString publicKey = response.getDevice().getAntiSpoofingKeyPair().getPublicKey();
Locator.get(mContext, FastPairHalfSheetManager.class).showHalfSheet(
- Cache.ScanFastPairStoreItem.newBuilder().setAddress(mBleAddress)
- .setAntiSpoofingPublicKey(publicKey)
- .build());
+ DataUtils.toScanFastPairStoreItem(response, mBleAddress));
} catch (IllegalStateException e) {
Log.e(TAG, "OEM does not construct fast pair data proxy correctly");
}
} else {
// Start to process bloom filter
- List<Account> accountList =
- FastPairDataProvider.getInstance().loadFastPairEligibleAccounts();
- byte[] bloomFilterByteArray = FastPairDecoder.getBloomFilter(fastPairDevice.getData());
- byte[] bloomFilterSalt = FastPairDecoder.getBloomFilterSalt(fastPairDevice.getData());
- for (Account account : accountList) {
- try {
+ try {
+ List<Account> accountList =
+ FastPairDataProvider.getInstance().loadFastPairEligibleAccounts();
+ Log.d(TAG, "account list size" + accountList.size());
+ byte[] bloomFilterByteArray = FastPairDecoder
+ .getBloomFilter(fastPairDevice.getData());
+ byte[] bloomFilterSalt = FastPairDecoder
+ .getBloomFilterSalt(fastPairDevice.getData());
+ if (bloomFilterByteArray == null || bloomFilterByteArray.length == 0) {
+ Log.d(TAG, "bloom filter byte size is 0");
+ return;
+ }
+ for (Account account : accountList) {
List<Data.FastPairDeviceWithAccountKey> listDevices =
FastPairDataProvider.getInstance().loadFastPairDevicesWithAccountKey(
account);
@@ -108,14 +107,15 @@
new BloomFilter(bloomFilterByteArray,
new FastPairBloomFilterHasher()), bloomFilterSalt);
if (recognizedDevice != null) {
- Log.d(TAG, "find matched device show notification to remind user to pair");
+ Log.d(TAG, "find matched device show notification to remind"
+ + " user to pair");
return;
}
- } catch (IllegalStateException e) {
- Log.e(TAG, "OEM does not construct fast pair data proxy correctly");
}
-
+ } catch (IllegalStateException e) {
+ Log.e(TAG, "OEM does not construct fast pair data proxy correctly");
}
+
}
}
diff --git a/nearby/service/java/com/android/server/nearby/fastpair/FastPairController.java b/nearby/service/java/com/android/server/nearby/fastpair/FastPairController.java
index cf8cd62..793e126 100644
--- a/nearby/service/java/com/android/server/nearby/fastpair/FastPairController.java
+++ b/nearby/service/java/com/android/server/nearby/fastpair/FastPairController.java
@@ -125,10 +125,7 @@
@Override
public void run() {
DiscoveryItem item = null;
- if (itemId != null) {
- // api call to get Fast Pair related info
- item = mFastPairCacheManager.getDiscoveryItem(itemId);
- } else if (discoveryItem != null) {
+ if (discoveryItem != null) {
try {
item = new DiscoveryItem(mContext,
Cache.StoredDiscoveryItem.parseFrom(discoveryItem));
@@ -136,6 +133,7 @@
Log.w(TAG,
"Error parsing serialized discovery item with size "
+ discoveryItem.length);
+ return;
}
}
@@ -196,6 +194,7 @@
Log.d(TAG, "FastPair: fastpairing, skip pair request");
return;
}
+ mIsFastPairing = true;
Log.d(TAG, "FastPair: start pair");
// Hide all "tap to pair" notifications until after the flow completes.
@@ -213,7 +212,7 @@
companionApp,
mFootprintsDeviceManager,
pairingProgressHandlerBase);
- mIsFastPairing = true;
+ mIsFastPairing = false;
}
/** Fixes a companion app package name with extra spaces. */
@@ -247,26 +246,26 @@
FastPairManager.processBackgroundTask(() -> {
Cache.StoredDiscoveryItem storedDiscoveryItem =
prepareStoredDiscoveryItemForFootprints(discoveryItem);
- if (storedDiscoveryItem != null) {
- byte[] hashValue =
- Hashing.sha256()
- .hashBytes(
- concat(accountKey, BluetoothAddress.decode(publicAddress)))
- .asBytes();
- FastPairUploadInfo uploadInfo =
- new FastPairUploadInfo(storedDiscoveryItem, ByteString.copyFrom(accountKey),
- ByteString.copyFrom(hashValue));
- // account data place holder here
- try {
- FastPairDataProvider.getInstance().optIn(new Account("empty", "empty"));
+ byte[] hashValue =
+ Hashing.sha256()
+ .hashBytes(
+ concat(accountKey, BluetoothAddress.decode(publicAddress)))
+ .asBytes();
+ FastPairUploadInfo uploadInfo =
+ new FastPairUploadInfo(storedDiscoveryItem, ByteString.copyFrom(accountKey),
+ ByteString.copyFrom(hashValue));
+ // account data place holder here
+ try {
+ List<Account> accountList =
+ FastPairDataProvider.getInstance().loadFastPairEligibleAccounts();
+ if (accountList.size() > 0) {
+ FastPairDataProvider.getInstance().optIn(accountList.get(0));
FastPairDataProvider.getInstance().upload(
- new Account("empty", "empty"), uploadInfo);
- } catch (IllegalStateException e) {
- Log.e(TAG, "OEM does not construct fast pair data proxy correctly");
+ accountList.get(0), uploadInfo);
}
-
+ } catch (IllegalStateException e) {
+ Log.e(TAG, "OEM does not construct fast pair data proxy correctly");
}
-
});
}
diff --git a/nearby/service/java/com/android/server/nearby/fastpair/FastPairManager.java b/nearby/service/java/com/android/server/nearby/fastpair/FastPairManager.java
index 7e2151d..9e1a718 100644
--- a/nearby/service/java/com/android/server/nearby/fastpair/FastPairManager.java
+++ b/nearby/service/java/com/android/server/nearby/fastpair/FastPairManager.java
@@ -16,20 +16,27 @@
package com.android.server.nearby.fastpair;
+import static com.android.server.nearby.fastpair.Constant.SETTINGS_TRUE_VALUE;
+import static com.android.server.nearby.fastpair.Constant.TAG;
+
import android.annotation.Nullable;
import android.annotation.WorkerThread;
import android.app.KeyguardManager;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothManager;
import android.content.BroadcastReceiver;
+import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.database.ContentObserver;
import android.nearby.FastPairDevice;
import android.nearby.NearbyDevice;
import android.nearby.NearbyManager;
import android.nearby.ScanCallback;
import android.nearby.ScanRequest;
+import android.net.Uri;
+import android.provider.Settings;
import android.util.Log;
import androidx.annotation.NonNull;
@@ -71,47 +78,32 @@
*/
public class FastPairManager {
+
private static final String ACTION_PREFIX = UserActionHandler.PREFIX;
private static final int WAIT_FOR_UNLOCK_MILLIS = 5000;
+
/** A notification ID which should be dismissed */
public static final String EXTRA_NOTIFICATION_ID = ACTION_PREFIX + "EXTRA_NOTIFICATION_ID";
public static final String ACTION_RESOURCES_APK = "android.nearby.SHOW_HALFSHEET";
private static Executor sFastPairExecutor;
+ private ContentObserver mFastPairScanChangeContentObserver = null;
+
final LocatorContextWrapper mLocatorContextWrapper;
final IntentFilter mIntentFilter;
final Locator mLocator;
- private boolean mAllowScan = false;
+ private boolean mScanEnabled = false;
private final BroadcastReceiver mScreenBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
- Log.d("FastPairService", " screen on");
- NearbyManager nearbyManager = (NearbyManager) mLocatorContextWrapper
- .getApplicationContext().getSystemService(Context.NEARBY_SERVICE);
-
- Log.d("FastPairService", " the nearby manager is " + nearbyManager);
-
- if (nearbyManager != null) {
- if (mAllowScan) {
- nearbyManager.startScan(
- new ScanRequest.Builder()
- .setScanType(ScanRequest.SCAN_TYPE_FAST_PAIR).build(),
- ForegroundThread.getExecutor(),
- mScanCallback);
- }
- } else {
- Log.d("FastPairService", " the nearby manager is null");
- }
-
- } else {
- Log.d("FastPairService", " screen off");
+ Log.d(TAG, "onReceive: ACTION_SCREEN_ON.");
+ invalidateScan();
}
}
};
-
public FastPairManager(LocatorContextWrapper contextWrapper) {
mLocatorContextWrapper = contextWrapper;
mIntentFilter = new IntentFilter();
@@ -131,16 +123,14 @@
public void onUpdated(@NonNull NearbyDevice device) {
FastPairDevice fastPairDevice = (FastPairDevice) device;
byte[] modelArray = FastPairDecoder.getModelId(fastPairDevice.getData());
- Log.d("FastPairService",
- "update model id" + Hex.bytesToStringLowercase(modelArray));
+ Log.d(TAG, "update model id" + Hex.bytesToStringLowercase(modelArray));
}
@Override
public void onLost(@NonNull NearbyDevice device) {
FastPairDevice fastPairDevice = (FastPairDevice) device;
byte[] modelArray = FastPairDecoder.getModelId(fastPairDevice.getData());
- Log.d("FastPairService",
- "lost model id" + Hex.bytesToStringLowercase(modelArray));
+ Log.d(TAG, "lost model id" + Hex.bytesToStringLowercase(modelArray));
}
};
@@ -155,6 +145,13 @@
.registerReceiver(mScreenBroadcastReceiver, mIntentFilter);
Locator.getFromContextWrapper(mLocatorContextWrapper, FastPairCacheManager.class);
+ try {
+ mScanEnabled = getScanEnabledFromSettings();
+ } catch (Settings.SettingNotFoundException e) {
+ Log.w(TAG,
+ "initiate: Failed to get initial scan enabled status from Settings.", e);
+ }
+ registerFastPairScanChangeContentObserver(mLocatorContextWrapper.getContentResolver());
}
/**
@@ -162,6 +159,10 @@
*/
public void cleanUp() {
mLocatorContextWrapper.getContext().unregisterReceiver(mScreenBroadcastReceiver);
+ if (mFastPairScanChangeContentObserver != null) {
+ mLocatorContextWrapper.getContentResolver().unregisterContentObserver(
+ mFastPairScanChangeContentObserver);
+ }
}
/**
@@ -212,18 +213,17 @@
boolean isBluetoothEnabled = bluetoothAdapter != null && bluetoothAdapter.isEnabled();
if (!isBluetoothEnabled) {
if (bluetoothAdapter == null || !bluetoothAdapter.enable()) {
- Log.d("FastPairManager", "FastPair: Failed to enable bluetooth");
+ Log.d(TAG, "FastPair: Failed to enable bluetooth");
return;
}
- Log.v("FastPairManager", "FastPair: Enabling bluetooth for fast pair");
+ Log.v(TAG, "FastPair: Enabling bluetooth for fast pair");
Locator.get(context, EventLoop.class)
.postRunnable(
new NamedRunnable("enableBluetoothToast") {
@Override
public void run() {
- Log.d("FastPairManager",
- "Enable bluetooth toast test");
+ Log.d(TAG, "Enable bluetooth toast test");
}
});
// Set up call back to call this function again once bluetooth has been
@@ -287,7 +287,7 @@
| ExecutionException
| PairingException
| GeneralSecurityException e) {
- Log.e("FastPairManager", "FastPair: Error");
+ Log.e(TAG, "FastPair: Error");
pairingProgressHandlerBase.onPairingFailed(e);
}
}
@@ -307,8 +307,7 @@
// pattern) So we use this method instead, which returns true when on the lock screen
// regardless.
if (keyguardManager.isKeyguardLocked()) {
- Log.v("FastPairManager",
- "FastPair: Screen is locked, waiting until unlocked "
+ Log.v(TAG, "FastPair: Screen is locked, waiting until unlocked "
+ "to show status notifications.");
try (SimpleBroadcastReceiver isUnlockedReceiver =
SimpleBroadcastReceiver.oneShotReceiver(
@@ -319,6 +318,28 @@
}
}
+ private void registerFastPairScanChangeContentObserver(ContentResolver resolver) {
+ mFastPairScanChangeContentObserver = new ContentObserver(ForegroundThread.getHandler()) {
+ @Override
+ public void onChange(boolean selfChange, Uri uri) {
+ super.onChange(selfChange, uri);
+ try {
+ setScanEnabled(getScanEnabledFromSettings());
+ } catch (Settings.SettingNotFoundException e) {
+ Log.e(TAG, "Failed to get scan switch updates in Settings page.", e);
+ }
+ }
+ };
+ try {
+ resolver.registerContentObserver(
+ Settings.Secure.getUriFor(Settings.Secure.FAST_PAIR_SCAN_ENABLED),
+ /* notifyForDescendants= */ false,
+ mFastPairScanChangeContentObserver);
+ } catch (SecurityException e) {
+ Log.e(TAG, "Failed to register content observer for fast pair scan.", e);
+ }
+ }
+
/**
* Processed task in a background thread
*/
@@ -339,6 +360,49 @@
}
/**
+ * Null when the Nearby Service is not available.
+ */
+ @Nullable
+ private NearbyManager getNearbyManager() {
+ return (NearbyManager) mLocatorContextWrapper
+ .getApplicationContext().getSystemService(Context.NEARBY_SERVICE);
+ }
+
+ private boolean getScanEnabledFromSettings() throws Settings.SettingNotFoundException {
+ return Settings.Secure.getInt(
+ mLocatorContextWrapper.getContext().getContentResolver(),
+ Settings.Secure.FAST_PAIR_SCAN_ENABLED) == SETTINGS_TRUE_VALUE;
+ }
+
+ private void setScanEnabled(boolean scanEnabled) {
+ if (mScanEnabled == scanEnabled) {
+ return;
+ }
+ mScanEnabled = scanEnabled;
+ invalidateScan();
+ }
+
+ /**
+ * Starts or stops scanning according to mAllowScan value.
+ */
+ private void invalidateScan() {
+ NearbyManager nearbyManager = getNearbyManager();
+ if (nearbyManager == null) {
+ Log.w(TAG, "invalidateScan: "
+ + "failed to start or stop scannning because NearbyManager is null.");
+ return;
+ }
+ if (mScanEnabled) {
+ nearbyManager.startScan(new ScanRequest.Builder()
+ .setScanType(ScanRequest.SCAN_TYPE_FAST_PAIR).build(),
+ ForegroundThread.getExecutor(),
+ mScanCallback);
+ } else {
+ nearbyManager.stopScan(mScanCallback);
+ }
+ }
+
+ /**
* Helper function to get bluetooth adapter.
*/
@Nullable
@@ -346,5 +410,4 @@
BluetoothManager manager = context.getSystemService(BluetoothManager.class);
return manager == null ? null : manager.getAdapter();
}
-
}
diff --git a/nearby/service/java/com/android/server/nearby/fastpair/halfsheet/FastPairHalfSheetManager.java b/nearby/service/java/com/android/server/nearby/fastpair/halfsheet/FastPairHalfSheetManager.java
index 9fdd01a..cfac904 100644
--- a/nearby/service/java/com/android/server/nearby/fastpair/halfsheet/FastPairHalfSheetManager.java
+++ b/nearby/service/java/com/android/server/nearby/fastpair/halfsheet/FastPairHalfSheetManager.java
@@ -48,6 +48,8 @@
*/
public class FastPairHalfSheetManager {
private static final String ACTIVITY_INTENT_ACTION = "android.nearby.SHOW_HALFSHEET";
+ private static final String HALF_SHEET_CLASS_NAME =
+ "com.android.nearby.halfsheet.HalfSheetActivity";
private String mHalfSheetApkPkgName;
private Context mContext;
@@ -65,22 +67,28 @@
* app can't get the correct component name.
*/
public void showHalfSheet(Cache.ScanFastPairStoreItem scanFastPairStoreItem) {
- if (mContext != null) {
- String packageName = getHalfSheetApkPkgName();
- HalfSheetCallback callback = new HalfSheetCallback();
- callback.setmFastPairController(Locator.get(mContext, FastPairController.class));
- Bundle bundle = new Bundle();
- bundle.putBinder(EXTRA_BINDER, callback);
- mContext
- .startActivityAsUser(new Intent(ACTIVITY_INTENT_ACTION)
- .putExtra(EXTRA_HALF_SHEET_INFO,
- scanFastPairStoreItem.toByteArray())
- .putExtra(EXTRA_HALF_SHEET_TYPE, DEVICE_PAIRING_FRAGMENT_TYPE)
- .putExtra(EXTRA_BUNDLE, bundle)
- .setComponent(new ComponentName(packageName,
- packageName + ".HalfSheetActivity")),
- UserHandle.CURRENT);
+ try {
+ if (mContext != null) {
+ String packageName = getHalfSheetApkPkgName();
+ HalfSheetCallback callback = new HalfSheetCallback();
+ callback.setmFastPairController(Locator.get(mContext, FastPairController.class));
+ Bundle bundle = new Bundle();
+ bundle.putBinder(EXTRA_BINDER, callback);
+ mContext
+ .startActivityAsUser(new Intent(ACTIVITY_INTENT_ACTION)
+ .putExtra(EXTRA_HALF_SHEET_INFO,
+ scanFastPairStoreItem.toByteArray())
+ .putExtra(EXTRA_HALF_SHEET_TYPE,
+ DEVICE_PAIRING_FRAGMENT_TYPE)
+ .putExtra(EXTRA_BUNDLE, bundle)
+ .setComponent(new ComponentName(packageName,
+ HALF_SHEET_CLASS_NAME)),
+ UserHandle.CURRENT);
+ }
+ } catch (IllegalStateException e) {
+ Log.e("FastPairHalfSheetManager",
+ "Can't resolve package that contains half sheet");
}
}
diff --git a/nearby/service/java/com/android/server/nearby/metrics/NearbyMetrics.java b/nearby/service/java/com/android/server/nearby/metrics/NearbyMetrics.java
new file mode 100644
index 0000000..75815f1
--- /dev/null
+++ b/nearby/service/java/com/android/server/nearby/metrics/NearbyMetrics.java
@@ -0,0 +1,85 @@
+/*
+ * 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.metrics;
+
+import android.nearby.NearbyDeviceParcelable;
+import android.nearby.ScanRequest;
+import android.os.WorkSource;
+
+import com.android.server.nearby.proto.NearbyStatsLog;
+
+/**
+ * A class to collect and report Nearby metrics.
+ */
+public class NearbyMetrics {
+ /**
+ * Logs a scan started event.
+ */
+ public static void logScanStarted(int scanSessionId, ScanRequest scanRequest) {
+ NearbyStatsLog.write(
+ NearbyStatsLog.NEARBY_DEVICE_SCAN_STATE_CHANGED,
+ getUid(scanRequest),
+ scanSessionId,
+ NearbyStatsLog
+ .NEARBY_DEVICE_SCAN_STATE_CHANGED__SCAN_STATE__NEARBY_SCAN_STATE_STARTED,
+ scanRequest.getScanType(),
+ 0,
+ 0,
+ "",
+ "");
+ }
+
+ /**
+ * Logs a scan stopped event.
+ */
+ public static void logScanStopped(int scanSessionId, ScanRequest scanRequest) {
+ NearbyStatsLog.write(
+ NearbyStatsLog.NEARBY_DEVICE_SCAN_STATE_CHANGED,
+ getUid(scanRequest),
+ scanSessionId,
+ NearbyStatsLog
+ .NEARBY_DEVICE_SCAN_STATE_CHANGED__SCAN_STATE__NEARBY_SCAN_STATE_STOPPED,
+ scanRequest.getScanType(),
+ 0,
+ 0,
+ "",
+ "");
+ }
+
+ /**
+ * Logs a scan device discovered event.
+ */
+ public static void logScanDeviceDiscovered(int scanSessionId, ScanRequest scanRequest,
+ NearbyDeviceParcelable nearbyDevice) {
+ NearbyStatsLog.write(
+ NearbyStatsLog.NEARBY_DEVICE_SCAN_STATE_CHANGED,
+ getUid(scanRequest),
+ scanSessionId,
+ NearbyStatsLog
+ .NEARBY_DEVICE_SCAN_STATE_CHANGED__SCAN_STATE__NEARBY_SCAN_STATE_DISCOVERED,
+ scanRequest.getScanType(),
+ nearbyDevice.getMedium(),
+ nearbyDevice.getRssi(),
+ nearbyDevice.getFastPairModelId(),
+ "");
+ }
+
+ private static int getUid(ScanRequest scanRequest) {
+ WorkSource workSource = scanRequest.getWorkSource();
+ return workSource.isEmpty() ? -1 : workSource.getUid(0);
+ }
+}
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 72c4b75..27f3acb 100644
--- a/nearby/service/java/com/android/server/nearby/provider/DiscoveryProviderManager.java
+++ b/nearby/service/java/com/android/server/nearby/provider/DiscoveryProviderManager.java
@@ -28,6 +28,7 @@
import com.android.internal.annotations.GuardedBy;
import com.android.server.nearby.injector.Injector;
+import com.android.server.nearby.metrics.NearbyMetrics;
import java.util.HashMap;
import java.util.Map;
@@ -59,6 +60,8 @@
record.getScanListener().onDiscovered(
PrivacyFilter.filter(record.getScanRequest().getScanType(),
nearbyDevice));
+ NearbyMetrics.logScanDeviceDiscovered(
+ record.hashCode(), record.getScanRequest(), nearbyDevice);
} catch (RemoteException e) {
Log.w(TAG, "DiscoveryProviderManager failed to report onDiscovered.", e);
}
@@ -89,8 +92,9 @@
startProviders(scanRequest);
- mScanTypeScanListenerRecordMap.put(listenerBinder,
- new ScanListenerRecord(scanRequest, listener));
+ ScanListenerRecord scanListenerRecord = new ScanListenerRecord(scanRequest, listener);
+ mScanTypeScanListenerRecordMap.put(listenerBinder, scanListenerRecord);
+ NearbyMetrics.logScanStarted(scanListenerRecord.hashCode(), scanRequest);
if (mScanMode < scanRequest.getScanMode()) {
mScanMode = scanRequest.getScanMode();
invalidateProviderScanMode();
@@ -113,6 +117,8 @@
ScanListenerRecord removedRecord = mScanTypeScanListenerRecordMap
.remove(listenerBinder);
+ NearbyMetrics.logScanStopped(
+ removedRecord.hashCode(), removedRecord.getScanRequest());
if (mScanTypeScanListenerRecordMap.isEmpty()) {
stopProviders();
return;
@@ -201,7 +207,7 @@
@Override
public int hashCode() {
- return Objects.hash(mScanListener, mScanRequest);
+ return Objects.hash(mScanListener, mScanRequest);
}
}
}
diff --git a/nearby/service/java/com/android/server/nearby/provider/FastPairDataProvider.java b/nearby/service/java/com/android/server/nearby/provider/FastPairDataProvider.java
index f8c16a1..40fefaf 100644
--- a/nearby/service/java/com/android/server/nearby/provider/FastPairDataProvider.java
+++ b/nearby/service/java/com/android/server/nearby/provider/FastPairDataProvider.java
@@ -90,7 +90,7 @@
FastPairAntispoofkeyDeviceMetadataRequestParcel requestParcel =
new FastPairAntispoofkeyDeviceMetadataRequestParcel();
requestParcel.modelId = modelId;
- return Utils.convertFastPairAntispoofkeyDeviceMetadataToGetObservedDeviceResponse(
+ return Utils.convertToGetObservedDeviceResponse(
mProxyFastPairDataProvider
.loadFastPairAntispoofkeyDeviceMetadata(requestParcel));
}
@@ -109,6 +109,7 @@
requestParcel.account = account;
requestParcel.requestType = FastPairDataProviderBase.MANAGE_REQUEST_ADD;
mProxyFastPairDataProvider.manageFastPairAccount(requestParcel);
+ return;
}
throw new IllegalStateException("No ProxyFastPairDataProvider yet constructed");
}
@@ -125,9 +126,9 @@
requestParcel.account = account;
requestParcel.requestType = FastPairDataProviderBase.MANAGE_REQUEST_ADD;
requestParcel.accountKeyDeviceMetadata =
- Utils.convertFastPairUploadInfoToFastPairAccountKeyDeviceMetadata(
- uploadInfo);
+ Utils.convertToFastPairAccountKeyDeviceMetadata(uploadInfo);
mProxyFastPairDataProvider.manageFastPairAccountDevice(requestParcel);
+ return;
}
throw new IllegalStateException("No ProxyFastPairDataProvider yet constructed");
}
@@ -151,7 +152,7 @@
FastPairAccountDevicesMetadataRequestParcel requestParcel =
new FastPairAccountDevicesMetadataRequestParcel();
requestParcel.account = account;
- return Utils.convertFastPairAccountKeyDevicesMetadataToFastPairDevicesWithAccountKey(
+ return Utils.convertToFastPairDevicesWithAccountKey(
mProxyFastPairDataProvider.loadFastPairAccountDevicesMetadata(requestParcel));
}
throw new IllegalStateException("No ProxyFastPairDataProvider yet constructed");
@@ -166,7 +167,7 @@
if (mProxyFastPairDataProvider != null) {
FastPairEligibleAccountsRequestParcel requestParcel =
new FastPairEligibleAccountsRequestParcel();
- return Utils.convertFastPairEligibleAccountsToAccountList(
+ return Utils.convertToAccountList(
mProxyFastPairDataProvider.loadFastPairEligibleAccounts(requestParcel));
}
throw new IllegalStateException("No ProxyFastPairDataProvider yet constructed");
diff --git a/nearby/service/java/com/android/server/nearby/provider/Utils.java b/nearby/service/java/com/android/server/nearby/provider/Utils.java
index a340b04..b84dfe9 100644
--- a/nearby/service/java/com/android/server/nearby/provider/Utils.java
+++ b/nearby/service/java/com/android/server/nearby/provider/Utils.java
@@ -41,9 +41,8 @@
*/
class Utils {
- static List<Data.FastPairDeviceWithAccountKey>
- convertFastPairAccountKeyDevicesMetadataToFastPairDevicesWithAccountKey(
- @Nullable FastPairAccountKeyDeviceMetadataParcel[] metadataParcels) {
+ static List<Data.FastPairDeviceWithAccountKey> convertToFastPairDevicesWithAccountKey(
+ @Nullable FastPairAccountKeyDeviceMetadataParcel[] metadataParcels) {
if (metadataParcels == null) {
return new ArrayList<Data.FastPairDeviceWithAccountKey>(0);
}
@@ -51,6 +50,9 @@
List<Data.FastPairDeviceWithAccountKey> fpDeviceList =
new ArrayList<>(metadataParcels.length);
for (FastPairAccountKeyDeviceMetadataParcel metadataParcel : metadataParcels) {
+ if (metadataParcel == null) {
+ continue;
+ }
Data.FastPairDeviceWithAccountKey.Builder fpDeviceBuilder =
Data.FastPairDeviceWithAccountKey.newBuilder();
if (metadataParcel.accountKey != null) {
@@ -68,15 +70,20 @@
if (metadataParcel.discoveryItem.actionUrl != null) {
storedDiscoveryItemBuilder.setActionUrl(metadataParcel.discoveryItem.actionUrl);
}
- storedDiscoveryItemBuilder.setActionUrlType(
- Cache.ResolvedUrlType.forNumber(
- metadataParcel.discoveryItem.actionUrlType));
+ Cache.ResolvedUrlType urlType = Cache.ResolvedUrlType.forNumber(
+ metadataParcel.discoveryItem.actionUrlType);
+ if (urlType != null) {
+ storedDiscoveryItemBuilder.setActionUrlType(urlType);
+ }
if (metadataParcel.discoveryItem.appName != null) {
storedDiscoveryItemBuilder.setAppName(metadataParcel.discoveryItem.appName);
}
- storedDiscoveryItemBuilder.setAttachmentType(
+ Cache.DiscoveryAttachmentType attachmentType =
Cache.DiscoveryAttachmentType.forNumber(
- metadataParcel.discoveryItem.attachmentType));
+ metadataParcel.discoveryItem.attachmentType);
+ if (attachmentType != null) {
+ storedDiscoveryItemBuilder.setAttachmentType(attachmentType);
+ }
if (metadataParcel.discoveryItem.authenticationPublicKeySecp256r1 != null) {
storedDiscoveryItemBuilder.setAuthenticationPublicKeySecp256R1(
ByteString.copyFrom(
@@ -86,9 +93,12 @@
storedDiscoveryItemBuilder.setBleRecordBytes(
ByteString.copyFrom(metadataParcel.discoveryItem.bleRecordBytes));
}
- storedDiscoveryItemBuilder.setDebugCategory(
+ Cache.StoredDiscoveryItem.DebugMessageCategory debugMessageCategory =
Cache.StoredDiscoveryItem.DebugMessageCategory.forNumber(
- metadataParcel.discoveryItem.debugCategory));
+ metadataParcel.discoveryItem.debugCategory);
+ if (debugMessageCategory != null) {
+ storedDiscoveryItemBuilder.setDebugCategory(debugMessageCategory);
+ }
if (metadataParcel.discoveryItem.debugMessage != null) {
storedDiscoveryItemBuilder.setDebugMessage(
metadataParcel.discoveryItem.debugMessage);
@@ -131,9 +141,12 @@
}
storedDiscoveryItemBuilder.setLastObservationTimestampMillis(
metadataParcel.discoveryItem.lastObservationTimestampMillis);
- storedDiscoveryItemBuilder.setLastUserExperience(
+ Cache.StoredDiscoveryItem.ExperienceType experienceType =
Cache.StoredDiscoveryItem.ExperienceType.forNumber(
- metadataParcel.discoveryItem.lastUserExperience));
+ metadataParcel.discoveryItem.lastUserExperience);
+ if (experienceType != null) {
+ storedDiscoveryItemBuilder.setLastUserExperience(experienceType);
+ }
storedDiscoveryItemBuilder.setLostMillis(metadataParcel.discoveryItem.lostMillis);
if (metadataParcel.discoveryItem.macAddress != null) {
storedDiscoveryItemBuilder.setMacAddress(
@@ -146,9 +159,12 @@
storedDiscoveryItemBuilder.setPendingAppInstallTimestampMillis(
metadataParcel.discoveryItem.pendingAppInstallTimestampMillis);
storedDiscoveryItemBuilder.setRssi(metadataParcel.discoveryItem.rssi);
- storedDiscoveryItemBuilder.setState(
+ Cache.StoredDiscoveryItem.State state =
Cache.StoredDiscoveryItem.State.forNumber(
- metadataParcel.discoveryItem.state));
+ metadataParcel.discoveryItem.state);
+ if (state != null) {
+ storedDiscoveryItemBuilder.setState(state);
+ }
if (metadataParcel.discoveryItem.title != null) {
storedDiscoveryItemBuilder.setTitle(metadataParcel.discoveryItem.title);
}
@@ -156,8 +172,11 @@
storedDiscoveryItemBuilder.setTriggerId(metadataParcel.discoveryItem.triggerId);
}
storedDiscoveryItemBuilder.setTxPower(metadataParcel.discoveryItem.txPower);
- storedDiscoveryItemBuilder.setType(
- Cache.NearbyType.forNumber(metadataParcel.discoveryItem.type));
+ Cache.NearbyType type =
+ Cache.NearbyType.forNumber(metadataParcel.discoveryItem.type);
+ if (type != null) {
+ storedDiscoveryItemBuilder.setType(type);
+ }
}
if (metadataParcel.metadata != null) {
FastPairStrings.Builder stringsBuilder = FastPairStrings.newBuilder();
@@ -250,22 +269,13 @@
metadataParcel.metadata.trueWirelessImageUrlRightBud);
}
fpInformationBuilder.setTrueWirelessImages(imagesBuilder.build());
- fpInformationBuilder.setDeviceType(
- Rpcs.DeviceType.forNumber(metadataParcel.metadata.deviceType));
+ Rpcs.DeviceType deviceType =
+ Rpcs.DeviceType.forNumber(metadataParcel.metadata.deviceType);
+ if (deviceType != null) {
+ fpInformationBuilder.setDeviceType(deviceType);
+ }
storedDiscoveryItemBuilder.setFastPairInformation(fpInformationBuilder.build());
- storedDiscoveryItemBuilder.setTxPower(metadataParcel.metadata.bleTxPower);
-
- if (metadataParcel.metadata.image != null) {
- storedDiscoveryItemBuilder.setIconPng(
- ByteString.copyFrom(metadataParcel.metadata.image));
- }
- if (metadataParcel.metadata.imageUrl != null) {
- storedDiscoveryItemBuilder.setIconFifeUrl(metadataParcel.metadata.imageUrl);
- }
- if (metadataParcel.metadata.intentUri != null) {
- storedDiscoveryItemBuilder.setActionUrl(metadataParcel.metadata.intentUri);
- }
}
fpDeviceBuilder.setDiscoveryItem(storedDiscoveryItemBuilder.build());
fpDeviceList.add(fpDeviceBuilder.build());
@@ -273,126 +283,230 @@
return fpDeviceList;
}
- static List<Account> convertFastPairEligibleAccountsToAccountList(
+ static List<Account> convertToAccountList(
@Nullable FastPairEligibleAccountParcel[] accountParcels) {
if (accountParcels == null) {
return new ArrayList<Account>(0);
}
List<Account> accounts = new ArrayList<Account>(accountParcels.length);
for (FastPairEligibleAccountParcel parcel : accountParcels) {
- accounts.add(parcel.account);
+ if (parcel != null && parcel.account != null) {
+ accounts.add(parcel.account);
+ }
}
return accounts;
}
+ private static @Nullable Rpcs.Device convertToDevice(
+ FastPairAntispoofkeyDeviceMetadataParcel metadata) {
+
+ Rpcs.Device.Builder deviceBuilder = Rpcs.Device.newBuilder();
+ if (metadata.antiSpoofPublicKey != null) {
+ deviceBuilder.setAntiSpoofingKeyPair(Rpcs.AntiSpoofingKeyPair.newBuilder()
+ .setPublicKey(ByteString.copyFrom(metadata.antiSpoofPublicKey))
+ .build());
+ }
+ if (metadata.deviceMetadata != null) {
+ Rpcs.TrueWirelessHeadsetImages.Builder imagesBuilder =
+ Rpcs.TrueWirelessHeadsetImages.newBuilder();
+ if (metadata.deviceMetadata.trueWirelessImageUrlLeftBud != null) {
+ imagesBuilder.setLeftBudUrl(metadata.deviceMetadata.trueWirelessImageUrlLeftBud);
+ }
+ if (metadata.deviceMetadata.trueWirelessImageUrlRightBud != null) {
+ imagesBuilder.setRightBudUrl(metadata.deviceMetadata.trueWirelessImageUrlRightBud);
+ }
+ if (metadata.deviceMetadata.trueWirelessImageUrlCase != null) {
+ imagesBuilder.setCaseUrl(metadata.deviceMetadata.trueWirelessImageUrlCase);
+ }
+ deviceBuilder.setTrueWirelessImages(imagesBuilder.build());
+ if (metadata.deviceMetadata.imageUrl != null) {
+ deviceBuilder.setImageUrl(metadata.deviceMetadata.imageUrl);
+ }
+ if (metadata.deviceMetadata.intentUri != null) {
+ deviceBuilder.setIntentUri(metadata.deviceMetadata.intentUri);
+ }
+ if (metadata.deviceMetadata.name != null) {
+ deviceBuilder.setName(metadata.deviceMetadata.name);
+ }
+ Rpcs.DeviceType deviceType =
+ Rpcs.DeviceType.forNumber(metadata.deviceMetadata.deviceType);
+ if (deviceType != null) {
+ deviceBuilder.setDeviceType(deviceType);
+ }
+ deviceBuilder.setBleTxPower(metadata.deviceMetadata.bleTxPower)
+ .setTriggerDistance(metadata.deviceMetadata.triggerDistance);
+ }
+
+ return deviceBuilder.build();
+ }
+
+ private static @Nullable ByteString convertToImage(
+ FastPairAntispoofkeyDeviceMetadataParcel metadata) {
+ if (metadata.deviceMetadata == null || metadata.deviceMetadata.image == null) {
+ return null;
+ }
+
+ return ByteString.copyFrom(metadata.deviceMetadata.image);
+ }
+
+ private static @Nullable Rpcs.ObservedDeviceStrings
+ convertToObservedDeviceStrings(FastPairAntispoofkeyDeviceMetadataParcel metadata) {
+ if (metadata.deviceMetadata == null) {
+ return null;
+ }
+
+ Rpcs.ObservedDeviceStrings.Builder stringsBuilder = Rpcs.ObservedDeviceStrings.newBuilder();
+ if (metadata.deviceMetadata.assistantSetupHalfSheet != null) {
+ stringsBuilder
+ .setAssistantSetupHalfSheet(metadata.deviceMetadata.assistantSetupHalfSheet);
+ }
+ if (metadata.deviceMetadata.assistantSetupNotification != null) {
+ stringsBuilder.setAssistantSetupNotification(
+ metadata.deviceMetadata.assistantSetupNotification);
+ }
+ if (metadata.deviceMetadata.confirmPinDescription != null) {
+ stringsBuilder.setConfirmPinDescription(metadata.deviceMetadata.confirmPinDescription);
+ }
+ if (metadata.deviceMetadata.confirmPinTitle != null) {
+ stringsBuilder.setConfirmPinTitle(metadata.deviceMetadata.confirmPinTitle);
+ }
+ if (metadata.deviceMetadata.connectSuccessCompanionAppInstalled != null) {
+ stringsBuilder.setConnectSuccessCompanionAppInstalled(
+ metadata.deviceMetadata.connectSuccessCompanionAppInstalled);
+ }
+ if (metadata.deviceMetadata.connectSuccessCompanionAppNotInstalled != null) {
+ stringsBuilder.setConnectSuccessCompanionAppNotInstalled(
+ metadata.deviceMetadata.connectSuccessCompanionAppNotInstalled);
+ }
+ if (metadata.deviceMetadata.downloadCompanionAppDescription != null) {
+ stringsBuilder.setDownloadCompanionAppDescription(
+ metadata.deviceMetadata.downloadCompanionAppDescription);
+ }
+ if (metadata.deviceMetadata.failConnectGoToSettingsDescription != null) {
+ stringsBuilder.setFailConnectGoToSettingsDescription(
+ metadata.deviceMetadata.failConnectGoToSettingsDescription);
+ }
+ if (metadata.deviceMetadata.fastPairTvConnectDeviceNoAccountDescription != null) {
+ stringsBuilder.setFastPairTvConnectDeviceNoAccountDescription(
+ metadata.deviceMetadata.fastPairTvConnectDeviceNoAccountDescription);
+ }
+ if (metadata.deviceMetadata.initialNotificationDescription != null) {
+ stringsBuilder.setInitialNotificationDescription(
+ metadata.deviceMetadata.initialNotificationDescription);
+ }
+ if (metadata.deviceMetadata.initialNotificationDescriptionNoAccount != null) {
+ stringsBuilder.setInitialNotificationDescriptionNoAccount(
+ metadata.deviceMetadata.initialNotificationDescriptionNoAccount);
+ }
+ if (metadata.deviceMetadata.initialPairingDescription != null) {
+ stringsBuilder.setInitialPairingDescription(
+ metadata.deviceMetadata.initialPairingDescription);
+ }
+ if (metadata.deviceMetadata.locale != null) {
+ stringsBuilder.setLocale(metadata.deviceMetadata.locale);
+ }
+ if (metadata.deviceMetadata.openCompanionAppDescription != null) {
+ stringsBuilder.setOpenCompanionAppDescription(
+ metadata.deviceMetadata.openCompanionAppDescription);
+ }
+ if (metadata.deviceMetadata.retroactivePairingDescription != null) {
+ stringsBuilder.setRetroactivePairingDescription(
+ metadata.deviceMetadata.retroactivePairingDescription);
+ }
+ if (metadata.deviceMetadata.subsequentPairingDescription != null) {
+ stringsBuilder.setSubsequentPairingDescription(
+ metadata.deviceMetadata.subsequentPairingDescription);
+ }
+ if (metadata.deviceMetadata.syncContactsDescription != null) {
+ stringsBuilder.setSyncContactsDescription(
+ metadata.deviceMetadata.syncContactsDescription);
+ }
+ if (metadata.deviceMetadata.syncContactsTitle != null) {
+ stringsBuilder.setSyncContactsTitle(
+ metadata.deviceMetadata.syncContactsTitle);
+ }
+ if (metadata.deviceMetadata.syncSmsDescription != null) {
+ stringsBuilder.setSyncSmsDescription(
+ metadata.deviceMetadata.syncSmsDescription);
+ }
+ if (metadata.deviceMetadata.syncSmsTitle != null) {
+ stringsBuilder.setSyncSmsTitle(
+ metadata.deviceMetadata.syncSmsTitle);
+ }
+ if (metadata.deviceMetadata.unableToConnectDescription != null) {
+ stringsBuilder.setUnableToConnectDescription(
+ metadata.deviceMetadata.unableToConnectDescription);
+ }
+ if (metadata.deviceMetadata.unableToConnectTitle != null) {
+ stringsBuilder.setUnableToConnectTitle(
+ metadata.deviceMetadata.unableToConnectTitle);
+ }
+ if (metadata.deviceMetadata.updateCompanionAppDescription != null) {
+ stringsBuilder.setUpdateCompanionAppDescription(
+ metadata.deviceMetadata.updateCompanionAppDescription);
+ }
+ if (metadata.deviceMetadata.waitLaunchCompanionAppDescription != null) {
+ stringsBuilder.setWaitLaunchCompanionAppDescription(
+ metadata.deviceMetadata.waitLaunchCompanionAppDescription);
+ }
+
+ return stringsBuilder.build();
+ }
+
static @Nullable Rpcs.GetObservedDeviceResponse
- convertFastPairAntispoofkeyDeviceMetadataToGetObservedDeviceResponse(
+ convertToGetObservedDeviceResponse(
@Nullable FastPairAntispoofkeyDeviceMetadataParcel metadata) {
if (metadata == null) {
return null;
}
- return Rpcs.GetObservedDeviceResponse.newBuilder()
- .setDevice(Rpcs.Device.newBuilder()
- .setAntiSpoofingKeyPair(Rpcs.AntiSpoofingKeyPair.newBuilder()
- .setPublicKey(ByteString.copyFrom(metadata.antiSpoofPublicKey))
- .build())
- .setTrueWirelessImages(Rpcs.TrueWirelessHeadsetImages.newBuilder()
- .setLeftBudUrl(
- metadata.deviceMetadata.trueWirelessImageUrlLeftBud)
- .setRightBudUrl(
- metadata.deviceMetadata
- .trueWirelessImageUrlRightBud)
- .setCaseUrl(
- metadata.deviceMetadata
- .trueWirelessImageUrlCase
- )
- .build())
- .setImageUrl(metadata.deviceMetadata.imageUrl)
- .setIntentUri(metadata.deviceMetadata.intentUri)
- .setBleTxPower(metadata.deviceMetadata.bleTxPower)
- .setTriggerDistance(metadata.deviceMetadata.triggerDistance)
- .setDeviceType(
- Rpcs.DeviceType.forNumber(metadata.deviceMetadata.deviceType))
- .build())
- .setImage(ByteString.copyFrom(metadata.deviceMetadata.image))
- .setStrings(Rpcs.ObservedDeviceStrings.newBuilder()
- .setAssistantSetupHalfSheet(metadata.deviceMetadata.assistantSetupHalfSheet)
- .setAssistantSetupNotification(
- metadata.deviceMetadata.assistantSetupNotification)
- .setConfirmPinDescription(metadata.deviceMetadata.confirmPinDescription)
- .setConfirmPinTitle(metadata.deviceMetadata.confirmPinTitle)
- .setConnectSuccessCompanionAppInstalled(
- metadata.deviceMetadata.connectSuccessCompanionAppInstalled)
- .setConnectSuccessCompanionAppNotInstalled(
- metadata.deviceMetadata.connectSuccessCompanionAppNotInstalled)
- .setDownloadCompanionAppDescription(
- metadata.deviceMetadata.downloadCompanionAppDescription)
- .setFailConnectGoToSettingsDescription(
- metadata.deviceMetadata.failConnectGoToSettingsDescription)
- .setFastPairTvConnectDeviceNoAccountDescription(
- metadata.deviceMetadata.fastPairTvConnectDeviceNoAccountDescription)
- .setInitialNotificationDescription(
- metadata.deviceMetadata.initialNotificationDescription)
- .setInitialNotificationDescriptionNoAccount(
- metadata.deviceMetadata.initialNotificationDescriptionNoAccount)
- .setInitialPairingDescription(
- metadata.deviceMetadata.initialPairingDescription)
- .setLocale(metadata.deviceMetadata.locale)
- .setOpenCompanionAppDescription(
- metadata.deviceMetadata.openCompanionAppDescription)
- .setRetroactivePairingDescription(
- metadata.deviceMetadata.retroactivePairingDescription)
- .setSubsequentPairingDescription(
- metadata.deviceMetadata.subsequentPairingDescription)
- .setSyncContactsDescription(
- metadata.deviceMetadata.syncContactsDescription)
- .setSyncContactsTitle(
- metadata.deviceMetadata.syncContactsTitle)
- .setSyncSmsDescription(
- metadata.deviceMetadata.syncSmsDescription)
- .setSyncSmsTitle(
- metadata.deviceMetadata.syncSmsTitle)
- .setUnableToConnectDescription(
- metadata.deviceMetadata.unableToConnectDescription)
- .setUnableToConnectTitle(
- metadata.deviceMetadata.unableToConnectTitle)
- .setUpdateCompanionAppDescription(
- metadata.deviceMetadata.updateCompanionAppDescription)
- .setWaitLaunchCompanionAppDescription(
- metadata.deviceMetadata.waitLaunchCompanionAppDescription)
- .build())
- .build();
+
+ Rpcs.GetObservedDeviceResponse.Builder responseBuilder =
+ Rpcs.GetObservedDeviceResponse.newBuilder();
+
+ Rpcs.Device device = convertToDevice(metadata);
+ if (device != null) {
+ responseBuilder.setDevice(device);
+ }
+ ByteString image = convertToImage(metadata);
+ if (image != null) {
+ responseBuilder.setImage(image);
+ }
+ Rpcs.ObservedDeviceStrings strings = convertToObservedDeviceStrings(metadata);
+ if (strings != null) {
+ responseBuilder.setStrings(strings);
+ }
+
+ return responseBuilder.build();
}
static @Nullable FastPairAccountKeyDeviceMetadataParcel
- convertFastPairUploadInfoToFastPairAccountKeyDeviceMetadata(
- FastPairUploadInfo uploadInfo) {
+ convertToFastPairAccountKeyDeviceMetadata(
+ @Nullable FastPairUploadInfo uploadInfo) {
if (uploadInfo == null) {
return null;
}
FastPairAccountKeyDeviceMetadataParcel accountKeyDeviceMetadataParcel =
new FastPairAccountKeyDeviceMetadataParcel();
- accountKeyDeviceMetadataParcel.accountKey = uploadInfo.getAccountKey().toByteArray();
- accountKeyDeviceMetadataParcel.sha256AccountKeyPublicAddress =
- uploadInfo.getSha256AccountKeyPublicAddress().toByteArray();
- accountKeyDeviceMetadataParcel.metadata =
- convertStoredDiscoveryItemToFastPairDeviceMetadata(
- uploadInfo.getStoredDiscoveryItem());
- accountKeyDeviceMetadataParcel.discoveryItem =
- convertStoredDiscoveryItemToFastPairDiscoveryItem(
- uploadInfo.getStoredDiscoveryItem());
+ if (uploadInfo.getAccountKey() != null) {
+ accountKeyDeviceMetadataParcel.accountKey = uploadInfo.getAccountKey().toByteArray();
+ }
+ if (uploadInfo.getSha256AccountKeyPublicAddress() != null) {
+ accountKeyDeviceMetadataParcel.sha256AccountKeyPublicAddress =
+ uploadInfo.getSha256AccountKeyPublicAddress().toByteArray();
+ }
+ if (uploadInfo.getStoredDiscoveryItem() != null) {
+ accountKeyDeviceMetadataParcel.metadata =
+ convertToFastPairDeviceMetadata(uploadInfo.getStoredDiscoveryItem());
+ accountKeyDeviceMetadataParcel.discoveryItem =
+ convertToFastPairDiscoveryItem(uploadInfo.getStoredDiscoveryItem());
+ }
return accountKeyDeviceMetadataParcel;
}
private static @Nullable FastPairDiscoveryItemParcel
- convertStoredDiscoveryItemToFastPairDiscoveryItem(
- @Nullable Cache.StoredDiscoveryItem storedDiscoveryItem) {
- if (storedDiscoveryItem == null) {
- return null;
- }
-
+ convertToFastPairDiscoveryItem(Cache.StoredDiscoveryItem storedDiscoveryItem) {
FastPairDiscoveryItemParcel discoveryItemParcel = new FastPairDiscoveryItemParcel();
discoveryItemParcel.actionUrl = storedDiscoveryItem.getActionUrl();
discoveryItemParcel.actionUrlType = storedDiscoveryItem.getActionUrlType().getNumber();
@@ -444,12 +558,7 @@
String updateCompanionAppDescription = bundle.getString("updateCompanionAppDescription");
*/
private static @Nullable FastPairDeviceMetadataParcel
- convertStoredDiscoveryItemToFastPairDeviceMetadata(
- @Nullable Cache.StoredDiscoveryItem storedDiscoveryItem) {
- if (storedDiscoveryItem == null) {
- return null;
- }
-
+ convertToFastPairDeviceMetadata(Cache.StoredDiscoveryItem storedDiscoveryItem) {
FastPairStrings fpStrings = storedDiscoveryItem.getFastPairStrings();
FastPairDeviceMetadataParcel metadataParcel = new FastPairDeviceMetadataParcel();
@@ -485,11 +594,6 @@
fpInformation.getTrueWirelessImages().getRightBudUrl();
metadataParcel.deviceType = fpInformation.getDeviceType().getNumber();
- metadataParcel.bleTxPower = storedDiscoveryItem.getTxPower();
- metadataParcel.image = storedDiscoveryItem.getIconPng().toByteArray();
- metadataParcel.imageUrl = storedDiscoveryItem.getIconFifeUrl();
- metadataParcel.intentUri = storedDiscoveryItem.getActionUrl();
-
return metadataParcel;
}
}
diff --git a/nearby/service/java/com/android/server/nearby/util/DataUtils.java b/nearby/service/java/com/android/server/nearby/util/DataUtils.java
new file mode 100644
index 0000000..ce738c8
--- /dev/null
+++ b/nearby/service/java/com/android/server/nearby/util/DataUtils.java
@@ -0,0 +1,100 @@
+/*
+ * 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.util;
+
+import androidx.annotation.NonNull;
+
+import service.proto.Cache.ScanFastPairStoreItem;
+import service.proto.Cache.StoredDiscoveryItem;
+import service.proto.FastPairString.FastPairStrings;
+import service.proto.Rpcs.Device;
+import service.proto.Rpcs.GetObservedDeviceResponse;
+import service.proto.Rpcs.ObservedDeviceStrings;
+
+/**
+ * Utils class converts different data types {@link ScanFastPairStoreItem},
+ * {@link StoredDiscoveryItem} and {@link GetObservedDeviceResponse},
+ *
+ */
+public final class DataUtils {
+
+ /**
+ * Converts a {@link GetObservedDeviceResponse} to a {@link ScanFastPairStoreItem}.
+ */
+ public static ScanFastPairStoreItem toScanFastPairStoreItem(
+ GetObservedDeviceResponse observedDeviceResponse, @NonNull String bleAddress) {
+ Device device = observedDeviceResponse.getDevice();
+ return ScanFastPairStoreItem.newBuilder()
+ .setAddress(bleAddress)
+ .setActionUrl(device.getIntentUri())
+ .setDeviceName(device.getName())
+ .setIconPng(observedDeviceResponse.getImage())
+ .setIconFifeUrl(device.getImageUrl())
+ .setAntiSpoofingPublicKey(device.getAntiSpoofingKeyPair().getPublicKey())
+ .setFastPairStrings(getFastPairStrings(observedDeviceResponse))
+ .build();
+ }
+
+ /**
+ * Prints readable string for a {@link FastPairStrings}
+ */
+ public static String toString(FastPairStrings fastPairStrings) {
+ return "FastPairStrings["
+ + "tapToPairWithAccount=" + fastPairStrings.getTapToPairWithAccount()
+ + ", tapToPairWithoutAccount=" + fastPairStrings.getTapToPairWithoutAccount()
+ + ", initialPairingDescription=" + fastPairStrings.getInitialPairingDescription()
+ + ", pairingFinishedCompanionAppInstalled="
+ + fastPairStrings.getPairingFinishedCompanionAppInstalled()
+ + ", pairingFinishedCompanionAppNotInstalled="
+ + fastPairStrings.getPairingFinishedCompanionAppNotInstalled()
+ + ", subsequentPairingDescription="
+ + fastPairStrings.getSubsequentPairingDescription()
+ + ", retroactivePairingDescription="
+ + fastPairStrings.getRetroactivePairingDescription()
+ + ", waitAppLaunchDescription=" + fastPairStrings.getWaitAppLaunchDescription()
+ + ", pairingFailDescription=" + fastPairStrings.getPairingFailDescription()
+ + ", assistantHalfSheetDescription="
+ + fastPairStrings.getAssistantHalfSheetDescription()
+ + ", assistantNotificationDescription="
+ + fastPairStrings.getAssistantNotificationDescription()
+ + ", fastPairTvConnectDeviceNoAccountDescription="
+ + fastPairStrings.getFastPairTvConnectDeviceNoAccountDescription()
+ + "]";
+ }
+
+ private static FastPairStrings getFastPairStrings(GetObservedDeviceResponse response) {
+ ObservedDeviceStrings strings = response.getStrings();
+ return FastPairStrings.newBuilder()
+ .setTapToPairWithAccount(strings.getInitialNotificationDescription())
+ .setTapToPairWithoutAccount(
+ strings.getInitialNotificationDescriptionNoAccount())
+ .setInitialPairingDescription(strings.getInitialPairingDescription())
+ .setPairingFinishedCompanionAppInstalled(
+ strings.getConnectSuccessCompanionAppInstalled())
+ .setPairingFinishedCompanionAppNotInstalled(
+ strings.getConnectSuccessCompanionAppNotInstalled())
+ .setSubsequentPairingDescription(strings.getSubsequentPairingDescription())
+ .setRetroactivePairingDescription(strings.getRetroactivePairingDescription())
+ .setWaitAppLaunchDescription(strings.getWaitLaunchCompanionAppDescription())
+ .setPairingFailDescription(strings.getFailConnectGoToSettingsDescription())
+ .setAssistantHalfSheetDescription(strings.getAssistantSetupHalfSheet())
+ .setAssistantNotificationDescription(strings.getAssistantSetupNotification())
+ .setFastPairTvConnectDeviceNoAccountDescription(
+ strings.getFastPairTvConnectDeviceNoAccountDescription())
+ .build();
+ }
+}
diff --git a/nearby/service/java/com/android/server/nearby/util/Environment.java b/nearby/service/java/com/android/server/nearby/util/Environment.java
index dc131e7..e7277cd 100644
--- a/nearby/service/java/com/android/server/nearby/util/Environment.java
+++ b/nearby/service/java/com/android/server/nearby/util/Environment.java
@@ -29,7 +29,7 @@
/**
* NEARBY apex name.
*/
- private static final String NEARBY_APEX_NAME = "com.android.nearby";
+ private static final String NEARBY_APEX_NAME = "com.android.tethering";
/**
* The path where the Nearby apex is mounted.
diff --git a/nearby/service/java/com/android/server/nearby/util/Hex.java b/nearby/service/java/com/android/server/nearby/util/Hex.java
index c827ec5..446204e 100644
--- a/nearby/service/java/com/android/server/nearby/util/Hex.java
+++ b/nearby/service/java/com/android/server/nearby/util/Hex.java
@@ -30,8 +30,8 @@
public static String bytesToStringLowercase(byte[] bytes) {
char[] hexChars = new char[bytes.length * 2];
int j = 0;
- for (int i = 0; i < bytes.length; i++) {
- int v = bytes[i] & 0xFF;
+ for (byte aByte : bytes) {
+ int v = aByte & 0xFF;
hexChars[j++] = HEX_LOWERCASE[v >>> 4];
hexChars[j++] = HEX_LOWERCASE[v & 0x0F];
}
diff --git a/nearby/tests/cts/fastpair/src/android/nearby/cts/CredentialElementTest.java b/nearby/tests/cts/fastpair/src/android/nearby/cts/CredentialElementTest.java
new file mode 100644
index 0000000..19a4a40
--- /dev/null
+++ b/nearby/tests/cts/fastpair/src/android/nearby/cts/CredentialElementTest.java
@@ -0,0 +1,63 @@
+/*
+ * 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 android.nearby.cts;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.nearby.CredentialElement;
+import android.os.Build;
+import android.os.Parcel;
+
+import androidx.annotation.RequiresApi;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Arrays;
+
+@RunWith(AndroidJUnit4.class)
+@RequiresApi(Build.VERSION_CODES.TIRAMISU)
+public class CredentialElementTest {
+ private static final String KEY = "SECRETE_ID";
+ private static final byte[] VALUE = new byte[]{1, 2, 3, 4};
+
+ @Test
+ public void testBuilder() {
+ CredentialElement element = new CredentialElement(KEY, VALUE);
+
+ assertThat(element.getKey()).isEqualTo(KEY);
+ assertThat(Arrays.equals(element.getValue(), VALUE)).isTrue();
+ }
+
+ @Test
+ public void testWriteParcel() {
+ CredentialElement element = new CredentialElement(KEY, VALUE);
+
+ Parcel parcel = Parcel.obtain();
+ element.writeToParcel(parcel, 0);
+ parcel.setDataPosition(0);
+ CredentialElement elementFromParcel = element.CREATOR.createFromParcel(
+ parcel);
+ parcel.recycle();
+
+ assertThat(elementFromParcel.getKey()).isEqualTo(KEY);
+ assertThat(Arrays.equals(elementFromParcel.getValue(), VALUE)).isTrue();
+ }
+
+}
diff --git a/nearby/tests/cts/fastpair/src/android/nearby/cts/DataElementTest.java b/nearby/tests/cts/fastpair/src/android/nearby/cts/DataElementTest.java
new file mode 100644
index 0000000..eb03a0d
--- /dev/null
+++ b/nearby/tests/cts/fastpair/src/android/nearby/cts/DataElementTest.java
@@ -0,0 +1,63 @@
+/*
+ * 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 android.nearby.cts;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.nearby.DataElement;
+import android.os.Build;
+import android.os.Parcel;
+
+import androidx.annotation.RequiresApi;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Arrays;
+
+
+@RunWith(AndroidJUnit4.class)
+@RequiresApi(Build.VERSION_CODES.TIRAMISU)
+public class DataElementTest {
+
+ private static final int KEY = 1234;
+ private static final byte[] VALUE = new byte[]{1, 1, 1, 1};
+
+ @Test
+ public void testBuilder() {
+ DataElement dataElement = new DataElement(KEY, VALUE);
+
+ assertThat(dataElement.getKey()).isEqualTo(KEY);
+ assertThat(Arrays.equals(dataElement.getValue(), VALUE)).isTrue();
+ }
+
+ @Test
+ public void testWriteParcel() {
+ DataElement dataElement = new DataElement(KEY, VALUE);
+
+ Parcel parcel = Parcel.obtain();
+ dataElement.writeToParcel(parcel, 0);
+ parcel.setDataPosition(0);
+ DataElement elementFromParcel = DataElement.CREATOR.createFromParcel(
+ parcel);
+ parcel.recycle();
+
+ assertThat(elementFromParcel.getKey()).isEqualTo(KEY);
+ assertThat(Arrays.equals(elementFromParcel.getValue(), VALUE)).isTrue();
+ }
+}
diff --git a/nearby/tests/cts/fastpair/src/android/nearby/cts/FastPairDataProviderBaseTest.java b/nearby/tests/cts/fastpair/src/android/nearby/cts/FastPairDataProviderBaseTest.java
index 743a8e7..71fc330 100644
--- a/nearby/tests/cts/fastpair/src/android/nearby/cts/FastPairDataProviderBaseTest.java
+++ b/nearby/tests/cts/fastpair/src/android/nearby/cts/FastPairDataProviderBaseTest.java
@@ -150,6 +150,7 @@
private static final int LAST_USER_EXPERIENCE = 93;
private static final long LOST_MILLIS = 393284L;
private static final String MAC_ADDRESS = "MAC_ADDRESS";
+ private static final String NAME = "NAME";
private static final String PACKAGE_NAME = "PACKAGE_NAME";
private static final long PENDING_APP_INSTALL_TIMESTAMP_MILLIS = 832393L;
private static final int RSSI = 9;
@@ -707,6 +708,7 @@
builder.setInitialPairingDescription(INITIAL_PAIRING_DESCRIPTION);
builder.setIntentUri(INTENT_URI);
builder.setLocale(LOCALE);
+ builder.setName(NAME);
builder.setOpenCompanionAppDescription(OPEN_COMPANION_APP_DESCRIPTION);
builder.setRetroactivePairingDescription(RETRO_ACTIVE_PAIRING_DESCRIPTION);
builder.setSubsequentPairingDescription(SUBSEQUENT_PAIRING_DESCRIPTION);
@@ -751,6 +753,7 @@
parcel.initialPairingDescription = INITIAL_PAIRING_DESCRIPTION;
parcel.intentUri = INTENT_URI;
parcel.locale = LOCALE;
+ parcel.name = NAME;
parcel.openCompanionAppDescription = OPEN_COMPANION_APP_DESCRIPTION;
parcel.retroactivePairingDescription = RETRO_ACTIVE_PAIRING_DESCRIPTION;
parcel.subsequentPairingDescription = SUBSEQUENT_PAIRING_DESCRIPTION;
@@ -890,6 +893,7 @@
assertThat(metadataParcel.intentUri).isEqualTo(INTENT_URI);
assertThat(metadataParcel.locale).isEqualTo(LOCALE);
+ assertThat(metadataParcel.name).isEqualTo(NAME);
assertThat(metadataParcel.openCompanionAppDescription).isEqualTo(
OPEN_COMPANION_APP_DESCRIPTION);
@@ -949,6 +953,7 @@
assertThat(metadata.getInitialPairingDescription()).isEqualTo(INITIAL_PAIRING_DESCRIPTION);
assertThat(metadata.getIntentUri()).isEqualTo(INTENT_URI);
assertThat(metadata.getLocale()).isEqualTo(LOCALE);
+ assertThat(metadata.getName()).isEqualTo(NAME);
assertThat(metadata.getOpenCompanionAppDescription())
.isEqualTo(OPEN_COMPANION_APP_DESCRIPTION);
assertThat(metadata.getRetroactivePairingDescription())
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 081626b..82e6615 100644
--- a/nearby/tests/cts/fastpair/src/android/nearby/cts/NearbyDeviceParcelableTest.java
+++ b/nearby/tests/cts/fastpair/src/android/nearby/cts/NearbyDeviceParcelableTest.java
@@ -21,32 +21,47 @@
import android.nearby.NearbyDevice;
import android.nearby.NearbyDeviceParcelable;
import android.os.Build;
+import android.os.Parcel;
import androidx.annotation.RequiresApi;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SdkSuppress;
+import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.util.Arrays;
+
@RunWith(AndroidJUnit4.class)
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
public class NearbyDeviceParcelableTest {
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 String FAST_PAIR_MODEL_ID = "1234";
+ private static final int RSSI = -60;
+
+ private NearbyDeviceParcelable.Builder mBuilder;
+
+ @Before
+ public void setUp() {
+ 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")
public void testToString() {
- NearbyDeviceParcelable nearbyDeviceParcelable = new NearbyDeviceParcelable.Builder()
- .setName("testDevice")
- .setMedium(NearbyDevice.Medium.BLE)
- .setRssi(-60)
- .setFastPairModelId(null)
- .setBluetoothAddress(BLUETOOTH_ADDRESS)
- .setData(null)
- .build();
+ NearbyDeviceParcelable nearbyDeviceParcelable =
+ mBuilder.setFastPairModelId(null).setData(null).build();
assertThat(nearbyDeviceParcelable.toString()).isEqualTo(
"NearbyDeviceParcelable[name=testDevice, medium=BLE, rssi=-60, "
@@ -59,7 +74,7 @@
public void test_defaultNullFields() {
NearbyDeviceParcelable nearbyDeviceParcelable = new NearbyDeviceParcelable.Builder()
.setMedium(NearbyDevice.Medium.BLE)
- .setRssi(-60)
+ .setRssi(RSSI)
.build();
assertThat(nearbyDeviceParcelable.getName()).isNull();
@@ -68,6 +83,56 @@
assertThat(nearbyDeviceParcelable.getData()).isNull();
assertThat(nearbyDeviceParcelable.getMedium()).isEqualTo(NearbyDevice.Medium.BLE);
- assertThat(nearbyDeviceParcelable.getRssi()).isEqualTo(-60);
+ assertThat(nearbyDeviceParcelable.getRssi()).isEqualTo(RSSI);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testWriteParcel() {
+ NearbyDeviceParcelable nearbyDeviceParcelable = mBuilder.build();
+
+ Parcel parcel = Parcel.obtain();
+ nearbyDeviceParcelable.writeToParcel(parcel, 0);
+ parcel.setDataPosition(0);
+ NearbyDeviceParcelable actualNearbyDevice = NearbyDeviceParcelable.CREATOR.createFromParcel(
+ parcel);
+ parcel.recycle();
+
+ assertThat(actualNearbyDevice.getRssi()).isEqualTo(RSSI);
+ assertThat(actualNearbyDevice.getFastPairModelId()).isEqualTo(FAST_PAIR_MODEL_ID);
+ assertThat(actualNearbyDevice.getBluetoothAddress()).isEqualTo(BLUETOOTH_ADDRESS);
+ assertThat(Arrays.equals(actualNearbyDevice.getData(), SCAN_DATA)).isTrue();
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testWriteParcel_nullModelId() {
+ NearbyDeviceParcelable nearbyDeviceParcelable =
+ mBuilder.setFastPairModelId(null).build();
+
+ Parcel parcel = Parcel.obtain();
+ nearbyDeviceParcelable.writeToParcel(parcel, 0);
+ parcel.setDataPosition(0);
+ NearbyDeviceParcelable actualNearbyDevice = NearbyDeviceParcelable.CREATOR.createFromParcel(
+ parcel);
+ parcel.recycle();
+
+ assertThat(actualNearbyDevice.getFastPairModelId()).isNull();
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testWriteParcel_nullBluetoothAddress() {
+ NearbyDeviceParcelable nearbyDeviceParcelable =
+ mBuilder.setBluetoothAddress(null).build();
+
+ Parcel parcel = Parcel.obtain();
+ nearbyDeviceParcelable.writeToParcel(parcel, 0);
+ parcel.setDataPosition(0);
+ NearbyDeviceParcelable actualNearbyDevice = NearbyDeviceParcelable.CREATOR.createFromParcel(
+ parcel);
+ parcel.recycle();
+
+ assertThat(actualNearbyDevice.getBluetoothAddress()).isNull();
}
}
diff --git a/nearby/tests/cts/fastpair/src/android/nearby/cts/NearbyDeviceTest.java b/nearby/tests/cts/fastpair/src/android/nearby/cts/NearbyDeviceTest.java
index aad3fca..f37800a 100644
--- a/nearby/tests/cts/fastpair/src/android/nearby/cts/NearbyDeviceTest.java
+++ b/nearby/tests/cts/fastpair/src/android/nearby/cts/NearbyDeviceTest.java
@@ -49,11 +49,11 @@
@SdkSuppress(minSdkVersion = 32, codeName = "T")
public void test_getMedium_fromChild() {
FastPairDevice fastPairDevice = new FastPairDevice.Builder()
- .setMedium(NearbyDevice.Medium.BLE)
+ .addMedium(NearbyDevice.Medium.BLE)
.setRssi(-60)
.build();
- assertThat(fastPairDevice.getMedium()).isEqualTo(1);
+ assertThat(fastPairDevice.getMediums()).contains(1);
assertThat(fastPairDevice.getRssi()).isEqualTo(-60);
}
}
diff --git a/nearby/tests/cts/fastpair/src/android/nearby/cts/NearbyManagerTest.java b/nearby/tests/cts/fastpair/src/android/nearby/cts/NearbyManagerTest.java
index 07e8558..f32ef12 100644
--- a/nearby/tests/cts/fastpair/src/android/nearby/cts/NearbyManagerTest.java
+++ b/nearby/tests/cts/fastpair/src/android/nearby/cts/NearbyManagerTest.java
@@ -16,12 +16,18 @@
package android.nearby.cts;
+import static android.nearby.PresenceCredential.IDENTITY_TYPE_PRIVATE;
+
import static org.mockito.Mockito.when;
import static org.mockito.MockitoAnnotations.initMocks;
import android.content.Context;
+import android.nearby.BroadcastCallback;
+import android.nearby.BroadcastRequest;
import android.nearby.NearbyDevice;
import android.nearby.NearbyManager;
+import android.nearby.PresenceBroadcastRequest;
+import android.nearby.PrivateCredential;
import android.nearby.ScanCallback;
import android.nearby.ScanRequest;
import android.os.Build;
@@ -35,6 +41,7 @@
import org.junit.runner.RunWith;
import org.mockito.Mock;
+import java.util.Collections;
import java.util.concurrent.Executors;
/**
@@ -44,9 +51,13 @@
@RunWith(AndroidJUnit4.class)
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
public class NearbyManagerTest {
+ private static final byte[] SALT = new byte[] {1, 2};
+ 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 int BLE_MEDIUM = 1;
- @Mock Context mContext;
- @Mock NearbyManager mNearbyManager;
+ @Mock private Context mContext;
+ @Mock private NearbyManager mNearbyManager;
@Before
public void setUp() {
@@ -79,4 +90,21 @@
mNearbyManager.startScan(scanRequest, Executors.newSingleThreadExecutor(), scanCallback);
mNearbyManager.stopScan(scanCallback);
}
+
+ @Test
+ public void testStartStopBroadcast() {
+ PrivateCredential credential = new PrivateCredential.Builder(SECRETE_ID, AUTHENTICITY_KEY)
+ .setIdentityType(IDENTITY_TYPE_PRIVATE)
+ .build();
+ BroadcastRequest broadcastRequest =
+ new PresenceBroadcastRequest.Builder(Collections.singletonList(BLE_MEDIUM), SALT)
+ .setCredential(credential)
+ .build();
+
+ BroadcastCallback callback = status -> {
+ };
+ mNearbyManager.startBroadcast(broadcastRequest, Executors.newSingleThreadExecutor(),
+ callback);
+ mNearbyManager.stopBroadcast(callback);
+ }
}
diff --git a/nearby/tests/cts/fastpair/src/android/nearby/cts/PresenceBroadcastRequestTest.java b/nearby/tests/cts/fastpair/src/android/nearby/cts/PresenceBroadcastRequestTest.java
new file mode 100644
index 0000000..a37cc67
--- /dev/null
+++ b/nearby/tests/cts/fastpair/src/android/nearby/cts/PresenceBroadcastRequestTest.java
@@ -0,0 +1,113 @@
+/*
+ * 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 android.nearby.cts;
+
+import static android.nearby.BroadcastRequest.BROADCAST_TYPE_NEARBY_PRESENCE;
+import static android.nearby.BroadcastRequest.PRESENCE_VERSION_V0;
+import static android.nearby.PresenceCredential.IDENTITY_TYPE_PRIVATE;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.nearby.DataElement;
+import android.nearby.PresenceBroadcastRequest;
+import android.nearby.PrivateCredential;
+import android.os.Build;
+import android.os.Parcel;
+
+import androidx.annotation.RequiresApi;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Arrays;
+import java.util.Collections;
+
+/**
+ * Tests for {@link PresenceBroadcastRequest}.
+ */
+@RunWith(AndroidJUnit4.class)
+@RequiresApi(Build.VERSION_CODES.TIRAMISU)
+public class PresenceBroadcastRequestTest {
+
+ private static final int VERSION = PRESENCE_VERSION_V0;
+ private static final int TX_POWER = 1;
+ private static final byte[] SALT = new byte[]{1, 2};
+ private static final int ACTION_ID = 123;
+ private static final int BLE_MEDIUM = 1;
+ 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[] METADATA_ENCRYPTION_KEY = new byte[]{1, 1, 3, 4, 5};
+ private static final int KEY = 1234;
+ private static final byte[] VALUE = new byte[]{1, 1, 1, 1};
+
+ private PresenceBroadcastRequest.Builder mBuilder;
+
+ @Before
+ public void setUp() {
+ PrivateCredential credential = new PrivateCredential.Builder(SECRETE_ID, AUTHENTICITY_KEY)
+ .setIdentityType(IDENTITY_TYPE_PRIVATE)
+ .setMetadataEncryptionKey(METADATA_ENCRYPTION_KEY)
+ .build();
+ DataElement element = new DataElement(KEY, VALUE);
+ mBuilder = new PresenceBroadcastRequest.Builder(Collections.singletonList(BLE_MEDIUM), SALT)
+ .setTxPower(TX_POWER)
+ .setVersion(VERSION)
+ .setCredential(credential)
+ .addAction(ACTION_ID)
+ .addExtendedProperty(element);
+ }
+
+ @Test
+ public void testBuilder() {
+ PresenceBroadcastRequest broadcastRequest = mBuilder.build();
+
+ assertThat(broadcastRequest.getVersion()).isEqualTo(VERSION);
+ assertThat(Arrays.equals(broadcastRequest.getSalt(), SALT)).isTrue();
+ assertThat(broadcastRequest.getTxPower()).isEqualTo(TX_POWER);
+ assertThat(broadcastRequest.getActions()).containsExactly(ACTION_ID);
+ assertThat(broadcastRequest.getExtendedProperties().get(0).getKey()).isEqualTo(
+ KEY);
+ assertThat(broadcastRequest.getMediums()).containsExactly(BLE_MEDIUM);
+ assertThat(broadcastRequest.getCredential().getIdentityType()).isEqualTo(
+ IDENTITY_TYPE_PRIVATE);
+ assertThat(broadcastRequest.getType()).isEqualTo(BROADCAST_TYPE_NEARBY_PRESENCE);
+ }
+
+ @Test
+ public void testWriteParcel() {
+ PresenceBroadcastRequest broadcastRequest = mBuilder.build();
+
+ Parcel parcel = Parcel.obtain();
+ broadcastRequest.writeToParcel(parcel, 0);
+ parcel.setDataPosition(0);
+ PresenceBroadcastRequest parcelRequest = PresenceBroadcastRequest.CREATOR.createFromParcel(
+ parcel);
+ parcel.recycle();
+
+ assertThat(parcelRequest.getTxPower()).isEqualTo(TX_POWER);
+ assertThat(parcelRequest.getActions()).containsExactly(ACTION_ID);
+ assertThat(parcelRequest.getExtendedProperties().get(0).getKey()).isEqualTo(
+ KEY);
+ assertThat(parcelRequest.getMediums()).containsExactly(BLE_MEDIUM);
+ assertThat(parcelRequest.getCredential().getIdentityType()).isEqualTo(
+ IDENTITY_TYPE_PRIVATE);
+ assertThat(parcelRequest.getType()).isEqualTo(BROADCAST_TYPE_NEARBY_PRESENCE);
+
+ }
+}
diff --git a/nearby/tests/cts/fastpair/src/android/nearby/cts/PresenceDeviceTest.java b/nearby/tests/cts/fastpair/src/android/nearby/cts/PresenceDeviceTest.java
new file mode 100644
index 0000000..a1b282d
--- /dev/null
+++ b/nearby/tests/cts/fastpair/src/android/nearby/cts/PresenceDeviceTest.java
@@ -0,0 +1,107 @@
+/*
+ * 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 android.nearby.cts;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.nearby.DataElement;
+import android.nearby.NearbyDevice;
+import android.nearby.PresenceDevice;
+import android.os.Build;
+import android.os.Parcel;
+
+import androidx.annotation.RequiresApi;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Arrays;
+
+/**
+ * Test for {@link PresenceDevice}.
+ */
+@RunWith(AndroidJUnit4.class)
+@RequiresApi(Build.VERSION_CODES.TIRAMISU)
+public class PresenceDeviceTest {
+ private static final int DEVICE_TYPE = PresenceDevice.DeviceType.PHONE;
+ private static final String DEVICE_ID = "123";
+ private static final String IMAGE_URL = "http://example.com/imageUrl";
+ private static final int RSSI = -40;
+ private static final int MEDIUM = NearbyDevice.Medium.BLE;
+ private static final String DEVICE_NAME = "testDevice";
+ private static final int KEY = 1234;
+ private static final byte[] VALUE = new byte[]{1, 1, 1, 1};
+ private static final byte[] SALT = new byte[]{2, 3};
+ private static final byte[] SECRET_ID = new byte[]{11, 13};
+ private static final byte[] ENCRYPTED_IDENTITY = new byte[]{1, 3, 5, 61};
+ private static final long DISCOVERY_MILLIS = 100L;
+
+ @Test
+ public void testBuilder() {
+ PresenceDevice device = new PresenceDevice.Builder()
+ .setDeviceType(DEVICE_TYPE)
+ .setDeviceId(DEVICE_ID)
+ .setDeviceImageUrl(IMAGE_URL)
+ .addExtendedProperty(new DataElement(KEY, VALUE))
+ .setRssi(RSSI)
+ .addMedium(MEDIUM)
+ .setName(DEVICE_NAME)
+ .setDiscoveryTimestampMillis(DISCOVERY_MILLIS)
+ .setSalt(SALT)
+ .setSecretId(SECRET_ID)
+ .setEncryptedIdentity(ENCRYPTED_IDENTITY)
+ .build();
+
+ assertThat(device.getDeviceType()).isEqualTo(DEVICE_TYPE);
+ assertThat(device.getDeviceId()).isEqualTo(DEVICE_ID);
+ assertThat(device.getDeviceImageUrl()).isEqualTo(IMAGE_URL);
+ DataElement dataElement = device.getExtendedProperties().get(0);
+ assertThat(dataElement.getKey()).isEqualTo(KEY);
+ assertThat(Arrays.equals(dataElement.getValue(), VALUE)).isTrue();
+ assertThat(device.getRssi()).isEqualTo(RSSI);
+ assertThat(device.getMediums()).containsExactly(MEDIUM);
+ assertThat(device.getName()).isEqualTo(DEVICE_NAME);
+ assertThat(Arrays.equals(device.getSalt(), SALT)).isTrue();
+ assertThat(Arrays.equals(device.getSecretId(), SECRET_ID)).isTrue();
+ assertThat(Arrays.equals(device.getEncryptedIdentity(), ENCRYPTED_IDENTITY)).isTrue();
+ assertThat(device.getDiscoveryTimestampMillis()).isEqualTo(DISCOVERY_MILLIS);
+ }
+
+ @Test
+ public void testWriteParcel() {
+ PresenceDevice device = new PresenceDevice.Builder()
+ .setDeviceId(DEVICE_ID)
+ .addExtendedProperty(new DataElement(KEY, VALUE))
+ .setRssi(RSSI)
+ .addMedium(MEDIUM)
+ .setName(DEVICE_NAME)
+ .build();
+
+ Parcel parcel = Parcel.obtain();
+ device.writeToParcel(parcel, 0);
+ parcel.setDataPosition(0);
+ PresenceDevice parcelDevice = PresenceDevice.CREATOR.createFromParcel(parcel);
+ parcel.recycle();
+
+ assertThat(parcelDevice.getDeviceId()).isEqualTo(DEVICE_ID);
+ assertThat(parcelDevice.getExtendedProperties().get(0).getKey()).isEqualTo(KEY);
+ assertThat(parcelDevice.getRssi()).isEqualTo(RSSI);
+ assertThat(parcelDevice.getMediums()).containsExactly(MEDIUM);
+ assertThat(parcelDevice.getName()).isEqualTo(DEVICE_NAME);
+ }
+}
diff --git a/nearby/tests/cts/fastpair/src/android/nearby/cts/PresenceScanFilterTest.java b/nearby/tests/cts/fastpair/src/android/nearby/cts/PresenceScanFilterTest.java
new file mode 100644
index 0000000..308be9e
--- /dev/null
+++ b/nearby/tests/cts/fastpair/src/android/nearby/cts/PresenceScanFilterTest.java
@@ -0,0 +1,91 @@
+/*
+ * 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 android.nearby.cts;
+
+import static android.nearby.PresenceCredential.IDENTITY_TYPE_PRIVATE;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.nearby.DataElement;
+import android.nearby.PresenceScanFilter;
+import android.nearby.PublicCredential;
+import android.nearby.ScanRequest;
+import android.os.Build;
+import android.os.Parcel;
+
+import androidx.annotation.RequiresApi;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Tests for {@link android.nearby.PresenceScanFilter}.
+ */
+@RunWith(AndroidJUnit4.class)
+@RequiresApi(Build.VERSION_CODES.TIRAMISU)
+public class PresenceScanFilterTest {
+
+ private static final int RSSI = -40;
+ private static final int ACTION = 123;
+ 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 int KEY = 1234;
+ private static final byte[] VALUE = new byte[]{1, 1, 1, 1};
+
+
+ private PublicCredential mPublicCredential =
+ new PublicCredential.Builder(SECRETE_ID, AUTHENTICITY_KEY)
+ .setIdentityType(IDENTITY_TYPE_PRIVATE)
+ .setPublicKey(PUBLIC_KEY).setEncryptedMetadata(ENCRYPTED_METADATA)
+ .setEncryptedMetadataKeyTag(METADATA_ENCRYPTION_KEY_TAG).build();
+ private PresenceScanFilter.Builder mBuilder = new PresenceScanFilter.Builder()
+ .setMaxPathLoss(RSSI)
+ .addCredential(mPublicCredential)
+ .addPresenceAction(ACTION)
+ .addExtendedProperty(new DataElement(KEY, VALUE));
+
+ @Test
+ public void testBuilder() {
+ PresenceScanFilter filter = mBuilder.build();
+
+ assertThat(filter.getMaxPathLoss()).isEqualTo(RSSI);
+ assertThat(filter.getCredentials().get(0).getIdentityType()).isEqualTo(
+ IDENTITY_TYPE_PRIVATE);
+ assertThat(filter.getPresenceActions()).containsExactly(ACTION);
+ assertThat(filter.getExtendedProperties().get(0).getKey()).isEqualTo(KEY);
+
+ }
+
+ @Test
+ public void testWriteParcel() {
+ PresenceScanFilter filter = mBuilder.build();
+
+ Parcel parcel = Parcel.obtain();
+ filter.writeToParcel(parcel, 0);
+ parcel.setDataPosition(0);
+ PresenceScanFilter parcelFilter = PresenceScanFilter.CREATOR.createFromParcel(parcel);
+ parcel.recycle();
+
+ assertThat(parcelFilter.getType()).isEqualTo(ScanRequest.SCAN_TYPE_NEARBY_PRESENCE);
+ assertThat(parcelFilter.getMaxPathLoss()).isEqualTo(RSSI);
+ assertThat(parcelFilter.getPresenceActions()).containsExactly(ACTION);
+ }
+}
diff --git a/nearby/tests/cts/fastpair/src/android/nearby/cts/PrivateCredentialTest.java b/nearby/tests/cts/fastpair/src/android/nearby/cts/PrivateCredentialTest.java
new file mode 100644
index 0000000..5242999
--- /dev/null
+++ b/nearby/tests/cts/fastpair/src/android/nearby/cts/PrivateCredentialTest.java
@@ -0,0 +1,100 @@
+/*
+ * 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 android.nearby.cts;
+
+import static android.nearby.PresenceCredential.CREDENTIAL_TYPE_PRIVATE;
+import static android.nearby.PresenceCredential.IDENTITY_TYPE_PRIVATE;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.nearby.CredentialElement;
+import android.nearby.PrivateCredential;
+import android.os.Build;
+import android.os.Parcel;
+
+import androidx.annotation.RequiresApi;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Arrays;
+
+/**
+ * Tests for {@link PrivateCredential}.
+ */
+@RunWith(AndroidJUnit4.class)
+@RequiresApi(Build.VERSION_CODES.TIRAMISU)
+public class PrivateCredentialTest {
+ private static final String DEVICE_NAME = "myDevice";
+ 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 String KEY = "SecreteId";
+ private static final byte[] VALUE = new byte[]{1, 2, 3, 4, 5};
+ private static final byte[] METADATA_ENCRYPTION_KEY = new byte[]{1, 1, 3, 4, 5};
+
+ private PrivateCredential.Builder mBuilder;
+
+ @Before
+ public void setUp() {
+ mBuilder = new PrivateCredential.Builder(SECRETE_ID, AUTHENTICITY_KEY)
+ .setIdentityType(IDENTITY_TYPE_PRIVATE)
+ .setDeviceName(DEVICE_NAME)
+ .setMetadataEncryptionKey(METADATA_ENCRYPTION_KEY)
+ .addCredentialElement(new CredentialElement(KEY, VALUE));
+ }
+
+ @Test
+ public void testBuilder() {
+ PrivateCredential credential = mBuilder.build();
+
+ assertThat(credential.getType()).isEqualTo(CREDENTIAL_TYPE_PRIVATE);
+ assertThat(credential.getIdentityType()).isEqualTo(IDENTITY_TYPE_PRIVATE);
+ assertThat(credential.getDeviceName()).isEqualTo(DEVICE_NAME);
+ assertThat(Arrays.equals(credential.getSecretId(), SECRETE_ID)).isTrue();
+ assertThat(Arrays.equals(credential.getAuthenticityKey(), AUTHENTICITY_KEY)).isTrue();
+ assertThat(Arrays.equals(credential.getMetadataEncryptionKey(),
+ METADATA_ENCRYPTION_KEY)).isTrue();
+ CredentialElement credentialElement = credential.getCredentialElements().get(0);
+ assertThat(credentialElement.getKey()).isEqualTo(KEY);
+ assertThat(Arrays.equals(credentialElement.getValue(), VALUE)).isTrue();
+ }
+
+ @Test
+ public void testWriteParcel() {
+ PrivateCredential credential = mBuilder.build();
+
+ Parcel parcel = Parcel.obtain();
+ credential.writeToParcel(parcel, 0);
+ parcel.setDataPosition(0);
+ PrivateCredential credentialFromParcel = PrivateCredential.CREATOR.createFromParcel(
+ parcel);
+ parcel.recycle();
+
+ assertThat(credentialFromParcel.getType()).isEqualTo(CREDENTIAL_TYPE_PRIVATE);
+ 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.getMetadataEncryptionKey(),
+ METADATA_ENCRYPTION_KEY)).isTrue();
+ CredentialElement credentialElement = credentialFromParcel.getCredentialElements().get(0);
+ assertThat(credentialElement.getKey()).isEqualTo(KEY);
+ assertThat(Arrays.equals(credentialElement.getValue(), VALUE)).isTrue();
+ }
+}
diff --git a/nearby/tests/cts/fastpair/src/android/nearby/cts/PublicCredentialTest.java b/nearby/tests/cts/fastpair/src/android/nearby/cts/PublicCredentialTest.java
new file mode 100644
index 0000000..f750951
--- /dev/null
+++ b/nearby/tests/cts/fastpair/src/android/nearby/cts/PublicCredentialTest.java
@@ -0,0 +1,102 @@
+/*
+ * 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 android.nearby.cts;
+
+import static android.nearby.PresenceCredential.CREDENTIAL_TYPE_PUBLIC;
+import static android.nearby.PresenceCredential.IDENTITY_TYPE_PRIVATE;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.nearby.CredentialElement;
+import android.nearby.PresenceCredential;
+import android.nearby.PublicCredential;
+import android.os.Build;
+import android.os.Parcel;
+
+import androidx.annotation.RequiresApi;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Arrays;
+
+/**
+ * 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 String KEY = "KEY";
+ 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)
+ .addCredentialElement(new CredentialElement(KEY, VALUE))
+ .setIdentityType(IDENTITY_TYPE_PRIVATE)
+ .setPublicKey(PUBLIC_KEY).setEncryptedMetadata(ENCRYPTED_METADATA)
+ .setEncryptedMetadataKeyTag(METADATA_ENCRYPTION_KEY_TAG);
+ }
+
+ @Test
+ public void testBuilder() {
+ PublicCredential credential = mBuilder.build();
+
+ assertThat(credential.getType()).isEqualTo(CREDENTIAL_TYPE_PUBLIC);
+ assertThat(credential.getIdentityType()).isEqualTo(IDENTITY_TYPE_PRIVATE);
+ assertThat(credential.getCredentialElements().get(0).getKey()).isEqualTo(KEY);
+ assertThat(Arrays.equals(credential.getSecretId(), SECRETE_ID)).isTrue();
+ 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();
+ }
+
+ @Test
+ public void testWriteParcel() {
+ PublicCredential credential = mBuilder.build();
+
+ Parcel parcel = Parcel.obtain();
+ credential.writeToParcel(parcel, 0);
+ parcel.setDataPosition(0);
+ 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.getPublicKey(), PUBLIC_KEY)).isTrue();
+ assertThat(Arrays.equals(credentialFromParcel.getEncryptedMetadata(),
+ ENCRYPTED_METADATA)).isTrue();
+ assertThat(Arrays.equals(credentialFromParcel.getEncryptedMetadataKeyTag(),
+ METADATA_ENCRYPTION_KEY_TAG)).isTrue();
+ }
+}
diff --git a/nearby/tests/cts/fastpair/src/android/nearby/cts/ScanRequestTest.java b/nearby/tests/cts/fastpair/src/android/nearby/cts/ScanRequestTest.java
index 3bb348b..86e764c 100644
--- a/nearby/tests/cts/fastpair/src/android/nearby/cts/ScanRequestTest.java
+++ b/nearby/tests/cts/fastpair/src/android/nearby/cts/ScanRequestTest.java
@@ -16,6 +16,7 @@
package android.nearby.cts;
+import static android.nearby.PresenceCredential.IDENTITY_TYPE_PRIVATE;
import static android.nearby.ScanRequest.SCAN_MODE_BALANCED;
import static android.nearby.ScanRequest.SCAN_MODE_LOW_LATENCY;
import static android.nearby.ScanRequest.SCAN_MODE_LOW_POWER;
@@ -27,6 +28,8 @@
import static com.google.common.truth.Truth.assertThat;
+import android.nearby.PresenceScanFilter;
+import android.nearby.PublicCredential;
import android.nearby.ScanRequest;
import android.os.Build;
import android.os.WorkSource;
@@ -45,6 +48,16 @@
private static final int UID = 1001;
private static final String APP_NAME = "android.nearby.tests";
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testScanType() {
+ ScanRequest request = new ScanRequest.Builder()
+ .setScanType(SCAN_TYPE_NEARBY_PRESENCE)
+ .build();
+
+ assertThat(request.getScanType()).isEqualTo(SCAN_TYPE_NEARBY_PRESENCE);
+ }
+
// Valid scan type must be set to one of ScanRequest#SCAN_TYPE_
@Test(expected = IllegalStateException.class)
@SdkSuppress(minSdkVersion = 32, codeName = "T")
@@ -62,7 +75,7 @@
assertThat(request.getScanMode()).isEqualTo(SCAN_MODE_LOW_POWER);
}
- /** Verify setting work source with null value in the scan request is allowed*/
+ /** Verify setting work source with null value in the scan request is allowed */
@Test
@SdkSuppress(minSdkVersion = 32, codeName = "T")
public void testSetWorkSource_nullValue() {
@@ -151,6 +164,36 @@
assertThat(ScanRequest.scanModeToString(-2)).isEqualTo("SCAN_MODE_INVALID");
}
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testScanFilter() {
+ final byte[] secretId = new byte[]{1, 2, 3, 4};
+ final byte[] authenticityKey = new byte[]{0, 1, 1, 1};
+ final byte[] publicKey = new byte[]{1, 1, 2, 2};
+ final byte[] encryptedMetadata = new byte[]{1, 2, 3, 4, 5};
+ final byte[] metadataEncryptionKeyTag = new byte[]{1, 1, 3, 4, 5};
+
+ PublicCredential credential = new PublicCredential.Builder(secretId, authenticityKey)
+ .setIdentityType(IDENTITY_TYPE_PRIVATE)
+ .setEncryptedMetadata(encryptedMetadata)
+ .setPublicKey(publicKey)
+ .setEncryptedMetadataKeyTag(metadataEncryptionKeyTag).build();
+
+ final int rssi = -40;
+ final int action = 123;
+ PresenceScanFilter filter = new PresenceScanFilter.Builder()
+ .addCredential(credential)
+ .setMaxPathLoss(rssi)
+ .addPresenceAction(action)
+ .build();
+
+ ScanRequest request = new ScanRequest.Builder().setScanType(
+ SCAN_TYPE_FAST_PAIR).addScanFilter(filter).build();
+
+ assertThat(request.getScanFilters()).isNotEmpty();
+ assertThat(request.getScanFilters().get(0).getMaxPathLoss()).isEqualTo(rssi);
+ }
+
private static WorkSource getWorkSource() {
return new WorkSource(UID, APP_NAME);
}
diff --git a/nearby/tests/unit/Android.bp b/nearby/tests/unit/Android.bp
index 93ab20a..9b5b14c 100644
--- a/nearby/tests/unit/Android.bp
+++ b/nearby/tests/unit/Android.bp
@@ -33,18 +33,14 @@
compile_multilib: "both",
static_libs: [
- "Robolectric_all-target",
"androidx.test.ext.junit",
"androidx.test.rules",
- "compatibility-device-util-axt",
"framework-nearby-static",
"guava",
"junit",
"libprotobuf-java-lite",
"mockito-target",
"platform-test-annotations",
- "robolectric_android-all-stub",
- "service-appsearch",
"service-nearby",
"truth-prebuilt",
],
diff --git a/nearby/tests/unit/src/com/android/server/nearby/common/bluetooth/fastpair/PreferencesTest.java b/nearby/tests/unit/src/com/android/server/nearby/common/bluetooth/fastpair/PreferencesTest.java
new file mode 100644
index 0000000..b40a5a5
--- /dev/null
+++ b/nearby/tests/unit/src/com/android/server/nearby/common/bluetooth/fastpair/PreferencesTest.java
@@ -0,0 +1,1277 @@
+/*
+ * Copyright (C) 2021 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.common.bluetooth.fastpair;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.platform.test.annotations.Presubmit;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SdkSuppress;
+import androidx.test.filters.SmallTest;
+
+import com.google.common.collect.ImmutableSet;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Unit tests for {@link Preferences}.
+ */
+@Presubmit
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class PreferencesTest {
+
+ private static final int FIRST_INT = 1505;
+ private static final int SECOND_INT = 1506;
+ private static final boolean FIRST_BOOL = true;
+ private static final boolean SECOND_BOOL = false;
+ private static final short FIRST_SHORT = 32;
+ private static final short SECOND_SHORT = 73;
+ private static final long FIRST_LONG = 9838L;
+ private static final long SECOND_LONG = 93935L;
+ private static final String FIRST_STRING = "FIRST_STRING";
+ private static final String SECOND_STRING = "SECOND_STRING";
+ private static final byte[] FIRST_BYTES = new byte[] {7, 9};
+ private static final byte[] SECOND_BYTES = new byte[] {2};
+ private static final ImmutableSet<Integer> FIRST_INT_SETS = ImmutableSet.of(6, 8);
+ private static final ImmutableSet<Integer> SECOND_INT_SETS = ImmutableSet.of(6, 8);
+ private static final Preferences.ExtraLoggingInformation FIRST_EXTRA_LOGGING_INFO =
+ Preferences.ExtraLoggingInformation.builder().setModelId("000006").build();
+ private static final Preferences.ExtraLoggingInformation SECOND_EXTRA_LOGGING_INFO =
+ Preferences.ExtraLoggingInformation.builder().setModelId("000007").build();
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testGattOperationTimeoutSeconds() {
+ Preferences prefs =
+ Preferences.builder().setGattOperationTimeoutSeconds(FIRST_INT).build();
+ assertThat(prefs.getGattOperationTimeoutSeconds()).isEqualTo(FIRST_INT);
+ assertThat(prefs.toBuilder().build().getGattOperationTimeoutSeconds())
+ .isEqualTo(FIRST_INT);
+
+ Preferences prefs2 =
+ Preferences.builder().setGattOperationTimeoutSeconds(SECOND_INT).build();
+ assertThat(prefs2.getGattOperationTimeoutSeconds()).isEqualTo(SECOND_INT);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testGattConnectionTimeoutSeconds() {
+ Preferences prefs =
+ Preferences.builder().setGattConnectionTimeoutSeconds(FIRST_INT).build();
+ assertThat(prefs.getGattConnectionTimeoutSeconds()).isEqualTo(FIRST_INT);
+ assertThat(prefs.toBuilder().build().getGattConnectionTimeoutSeconds())
+ .isEqualTo(FIRST_INT);
+
+ Preferences prefs2 =
+ Preferences.builder().setGattConnectionTimeoutSeconds(SECOND_INT).build();
+ assertThat(prefs2.getGattConnectionTimeoutSeconds()).isEqualTo(SECOND_INT);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testBluetoothToggleTimeoutSeconds() {
+ Preferences prefs =
+ Preferences.builder().setBluetoothToggleTimeoutSeconds(FIRST_INT).build();
+ assertThat(prefs.getBluetoothToggleTimeoutSeconds()).isEqualTo(FIRST_INT);
+ assertThat(prefs.toBuilder().build().getBluetoothToggleTimeoutSeconds())
+ .isEqualTo(FIRST_INT);
+
+ Preferences prefs2 =
+ Preferences.builder().setBluetoothToggleTimeoutSeconds(SECOND_INT).build();
+ assertThat(prefs2.getBluetoothToggleTimeoutSeconds()).isEqualTo(SECOND_INT);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testBluetoothToggleSleepSeconds() {
+ Preferences prefs =
+ Preferences.builder().setBluetoothToggleSleepSeconds(FIRST_INT).build();
+ assertThat(prefs.getBluetoothToggleSleepSeconds()).isEqualTo(FIRST_INT);
+ assertThat(prefs.toBuilder().build().getBluetoothToggleSleepSeconds())
+ .isEqualTo(FIRST_INT);
+
+ Preferences prefs2 =
+ Preferences.builder().setBluetoothToggleSleepSeconds(SECOND_INT).build();
+ assertThat(prefs2.getBluetoothToggleSleepSeconds()).isEqualTo(SECOND_INT);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testClassicDiscoveryTimeoutSeconds() {
+ Preferences prefs =
+ Preferences.builder().setClassicDiscoveryTimeoutSeconds(FIRST_INT).build();
+ assertThat(prefs.getClassicDiscoveryTimeoutSeconds()).isEqualTo(FIRST_INT);
+ assertThat(prefs.toBuilder().build().getClassicDiscoveryTimeoutSeconds())
+ .isEqualTo(FIRST_INT);
+
+ Preferences prefs2 =
+ Preferences.builder().setClassicDiscoveryTimeoutSeconds(SECOND_INT).build();
+ assertThat(prefs2.getClassicDiscoveryTimeoutSeconds()).isEqualTo(SECOND_INT);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testNumDiscoverAttempts() {
+ Preferences prefs =
+ Preferences.builder().setNumDiscoverAttempts(FIRST_INT).build();
+ assertThat(prefs.getNumDiscoverAttempts()).isEqualTo(FIRST_INT);
+ assertThat(prefs.toBuilder().build().getNumDiscoverAttempts())
+ .isEqualTo(FIRST_INT);
+
+ Preferences prefs2 =
+ Preferences.builder().setNumDiscoverAttempts(SECOND_INT).build();
+ assertThat(prefs2.getNumDiscoverAttempts()).isEqualTo(SECOND_INT);
+ }
+
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testDiscoveryRetrySleepSeconds() {
+ Preferences prefs =
+ Preferences.builder().setDiscoveryRetrySleepSeconds(FIRST_INT).build();
+ assertThat(prefs.getDiscoveryRetrySleepSeconds()).isEqualTo(FIRST_INT);
+ assertThat(prefs.toBuilder().build().getDiscoveryRetrySleepSeconds())
+ .isEqualTo(FIRST_INT);
+
+ Preferences prefs2 =
+ Preferences.builder().setDiscoveryRetrySleepSeconds(SECOND_INT).build();
+ assertThat(prefs2.getDiscoveryRetrySleepSeconds()).isEqualTo(SECOND_INT);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testSdpTimeoutSeconds() {
+ Preferences prefs =
+ Preferences.builder().setSdpTimeoutSeconds(FIRST_INT).build();
+ assertThat(prefs.getSdpTimeoutSeconds()).isEqualTo(FIRST_INT);
+ assertThat(prefs.toBuilder().build().getSdpTimeoutSeconds())
+ .isEqualTo(FIRST_INT);
+
+ Preferences prefs2 =
+ Preferences.builder().setSdpTimeoutSeconds(SECOND_INT).build();
+ assertThat(prefs2.getSdpTimeoutSeconds()).isEqualTo(SECOND_INT);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testNumSdpAttempts() {
+ Preferences prefs =
+ Preferences.builder().setNumSdpAttempts(FIRST_INT).build();
+ assertThat(prefs.getNumSdpAttempts()).isEqualTo(FIRST_INT);
+ assertThat(prefs.toBuilder().build().getNumSdpAttempts())
+ .isEqualTo(FIRST_INT);
+
+ Preferences prefs2 =
+ Preferences.builder().setNumSdpAttempts(SECOND_INT).build();
+ assertThat(prefs2.getNumSdpAttempts()).isEqualTo(SECOND_INT);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testNumCreateBondAttempts() {
+ Preferences prefs =
+ Preferences.builder().setNumCreateBondAttempts(FIRST_INT).build();
+ assertThat(prefs.getNumCreateBondAttempts()).isEqualTo(FIRST_INT);
+ assertThat(prefs.toBuilder().build().getNumCreateBondAttempts())
+ .isEqualTo(FIRST_INT);
+
+ Preferences prefs2 =
+ Preferences.builder().setNumCreateBondAttempts(SECOND_INT).build();
+ assertThat(prefs2.getNumCreateBondAttempts()).isEqualTo(SECOND_INT);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testNumConnectAttempts() {
+ Preferences prefs =
+ Preferences.builder().setNumConnectAttempts(FIRST_INT).build();
+ assertThat(prefs.getNumConnectAttempts()).isEqualTo(FIRST_INT);
+ assertThat(prefs.toBuilder().build().getNumConnectAttempts())
+ .isEqualTo(FIRST_INT);
+
+ Preferences prefs2 =
+ Preferences.builder().setNumConnectAttempts(SECOND_INT).build();
+ assertThat(prefs2.getNumConnectAttempts()).isEqualTo(SECOND_INT);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testNumWriteAccountKeyAttempts() {
+ Preferences prefs =
+ Preferences.builder().setNumWriteAccountKeyAttempts(FIRST_INT).build();
+ assertThat(prefs.getNumWriteAccountKeyAttempts()).isEqualTo(FIRST_INT);
+ assertThat(prefs.toBuilder().build().getNumWriteAccountKeyAttempts())
+ .isEqualTo(FIRST_INT);
+
+ Preferences prefs2 =
+ Preferences.builder().setNumWriteAccountKeyAttempts(SECOND_INT).build();
+ assertThat(prefs2.getNumWriteAccountKeyAttempts()).isEqualTo(SECOND_INT);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testBluetoothStatePollingMillis() {
+ Preferences prefs =
+ Preferences.builder().setBluetoothStatePollingMillis(FIRST_INT).build();
+ assertThat(prefs.getBluetoothStatePollingMillis()).isEqualTo(FIRST_INT);
+ assertThat(prefs.toBuilder().build().getBluetoothStatePollingMillis())
+ .isEqualTo(FIRST_INT);
+
+ Preferences prefs2 =
+ Preferences.builder().setBluetoothStatePollingMillis(SECOND_INT).build();
+ assertThat(prefs2.getBluetoothStatePollingMillis()).isEqualTo(SECOND_INT);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testNumAttempts() {
+ Preferences prefs =
+ Preferences.builder().setNumAttempts(FIRST_INT).build();
+ assertThat(prefs.getNumAttempts()).isEqualTo(FIRST_INT);
+ assertThat(prefs.toBuilder().build().getNumAttempts())
+ .isEqualTo(FIRST_INT);
+
+ Preferences prefs2 =
+ Preferences.builder().setNumAttempts(SECOND_INT).build();
+ assertThat(prefs2.getNumAttempts()).isEqualTo(SECOND_INT);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testRemoveBondTimeoutSeconds() {
+ Preferences prefs =
+ Preferences.builder().setRemoveBondTimeoutSeconds(FIRST_INT).build();
+ assertThat(prefs.getRemoveBondTimeoutSeconds()).isEqualTo(FIRST_INT);
+ assertThat(prefs.toBuilder().build().getRemoveBondTimeoutSeconds())
+ .isEqualTo(FIRST_INT);
+
+ Preferences prefs2 =
+ Preferences.builder().setRemoveBondTimeoutSeconds(SECOND_INT).build();
+ assertThat(prefs2.getRemoveBondTimeoutSeconds()).isEqualTo(SECOND_INT);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testRemoveBondSleepMillis() {
+ Preferences prefs =
+ Preferences.builder().setRemoveBondSleepMillis(FIRST_INT).build();
+ assertThat(prefs.getRemoveBondSleepMillis()).isEqualTo(FIRST_INT);
+ assertThat(prefs.toBuilder().build().getRemoveBondSleepMillis())
+ .isEqualTo(FIRST_INT);
+
+ Preferences prefs2 =
+ Preferences.builder().setRemoveBondSleepMillis(SECOND_INT).build();
+ assertThat(prefs2.getRemoveBondSleepMillis()).isEqualTo(SECOND_INT);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testCreateBondTimeoutSeconds() {
+ Preferences prefs =
+ Preferences.builder().setCreateBondTimeoutSeconds(FIRST_INT).build();
+ assertThat(prefs.getCreateBondTimeoutSeconds()).isEqualTo(FIRST_INT);
+ assertThat(prefs.toBuilder().build().getCreateBondTimeoutSeconds())
+ .isEqualTo(FIRST_INT);
+
+ Preferences prefs2 =
+ Preferences.builder().setCreateBondTimeoutSeconds(SECOND_INT).build();
+ assertThat(prefs2.getCreateBondTimeoutSeconds()).isEqualTo(SECOND_INT);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testHidCreateBondTimeoutSeconds() {
+ Preferences prefs =
+ Preferences.builder().setHidCreateBondTimeoutSeconds(FIRST_INT).build();
+ assertThat(prefs.getHidCreateBondTimeoutSeconds()).isEqualTo(FIRST_INT);
+ assertThat(prefs.toBuilder().build().getHidCreateBondTimeoutSeconds())
+ .isEqualTo(FIRST_INT);
+
+ Preferences prefs2 =
+ Preferences.builder().setHidCreateBondTimeoutSeconds(SECOND_INT).build();
+ assertThat(prefs2.getHidCreateBondTimeoutSeconds()).isEqualTo(SECOND_INT);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testProxyTimeoutSeconds() {
+ Preferences prefs =
+ Preferences.builder().setProxyTimeoutSeconds(FIRST_INT).build();
+ assertThat(prefs.getProxyTimeoutSeconds()).isEqualTo(FIRST_INT);
+ assertThat(prefs.toBuilder().build().getProxyTimeoutSeconds())
+ .isEqualTo(FIRST_INT);
+
+ Preferences prefs2 =
+ Preferences.builder().setProxyTimeoutSeconds(SECOND_INT).build();
+ assertThat(prefs2.getProxyTimeoutSeconds()).isEqualTo(SECOND_INT);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testWriteAccountKeySleepMillis() {
+ Preferences prefs =
+ Preferences.builder().setWriteAccountKeySleepMillis(FIRST_INT).build();
+ assertThat(prefs.getWriteAccountKeySleepMillis()).isEqualTo(FIRST_INT);
+ assertThat(prefs.toBuilder().build().getWriteAccountKeySleepMillis())
+ .isEqualTo(FIRST_INT);
+
+ Preferences prefs2 =
+ Preferences.builder().setWriteAccountKeySleepMillis(SECOND_INT).build();
+ assertThat(prefs2.getWriteAccountKeySleepMillis()).isEqualTo(SECOND_INT);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testPairFailureCounts() {
+ Preferences prefs =
+ Preferences.builder().setPairFailureCounts(FIRST_INT).build();
+ assertThat(prefs.getPairFailureCounts()).isEqualTo(FIRST_INT);
+ assertThat(prefs.toBuilder().build().getPairFailureCounts())
+ .isEqualTo(FIRST_INT);
+
+ Preferences prefs2 =
+ Preferences.builder().setPairFailureCounts(SECOND_INT).build();
+ assertThat(prefs2.getPairFailureCounts()).isEqualTo(SECOND_INT);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testCreateBondTransportType() {
+ Preferences prefs =
+ Preferences.builder().setCreateBondTransportType(FIRST_INT).build();
+ assertThat(prefs.getCreateBondTransportType()).isEqualTo(FIRST_INT);
+ assertThat(prefs.toBuilder().build().getCreateBondTransportType())
+ .isEqualTo(FIRST_INT);
+
+ Preferences prefs2 =
+ Preferences.builder().setCreateBondTransportType(SECOND_INT).build();
+ assertThat(prefs2.getCreateBondTransportType()).isEqualTo(SECOND_INT);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testGattConnectRetryTimeoutMillis() {
+ Preferences prefs =
+ Preferences.builder().setGattConnectRetryTimeoutMillis(FIRST_INT).build();
+ assertThat(prefs.getGattConnectRetryTimeoutMillis()).isEqualTo(FIRST_INT);
+ assertThat(prefs.toBuilder().build().getGattConnectRetryTimeoutMillis())
+ .isEqualTo(FIRST_INT);
+
+ Preferences prefs2 =
+ Preferences.builder().setGattConnectRetryTimeoutMillis(SECOND_INT).build();
+ assertThat(prefs2.getGattConnectRetryTimeoutMillis()).isEqualTo(SECOND_INT);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testNumSdpAttemptsAfterBonded() {
+ Preferences prefs =
+ Preferences.builder().setNumSdpAttemptsAfterBonded(FIRST_INT).build();
+ assertThat(prefs.getNumSdpAttemptsAfterBonded()).isEqualTo(FIRST_INT);
+ assertThat(prefs.toBuilder().build().getNumSdpAttemptsAfterBonded())
+ .isEqualTo(FIRST_INT);
+
+ Preferences prefs2 =
+ Preferences.builder().setNumSdpAttemptsAfterBonded(SECOND_INT).build();
+ assertThat(prefs2.getNumSdpAttemptsAfterBonded()).isEqualTo(SECOND_INT);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testSameModelIdPairedDeviceCount() {
+ Preferences prefs =
+ Preferences.builder().setSameModelIdPairedDeviceCount(FIRST_INT).build();
+ assertThat(prefs.getSameModelIdPairedDeviceCount()).isEqualTo(FIRST_INT);
+ assertThat(prefs.toBuilder().build().getSameModelIdPairedDeviceCount())
+ .isEqualTo(FIRST_INT);
+
+ Preferences prefs2 =
+ Preferences.builder().setSameModelIdPairedDeviceCount(SECOND_INT).build();
+ assertThat(prefs2.getSameModelIdPairedDeviceCount()).isEqualTo(SECOND_INT);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testIgnoreDiscoveryError() {
+ Preferences prefs =
+ Preferences.builder().setIgnoreDiscoveryError(FIRST_BOOL).build();
+ assertThat(prefs.getIgnoreDiscoveryError()).isEqualTo(FIRST_BOOL);
+ assertThat(prefs.toBuilder().build().getIgnoreDiscoveryError())
+ .isEqualTo(FIRST_BOOL);
+
+ Preferences prefs2 =
+ Preferences.builder().setIgnoreDiscoveryError(SECOND_BOOL).build();
+ assertThat(prefs2.getIgnoreDiscoveryError()).isEqualTo(SECOND_BOOL);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testToggleBluetoothOnFailure() {
+ Preferences prefs =
+ Preferences.builder().setToggleBluetoothOnFailure(FIRST_BOOL).build();
+ assertThat(prefs.getToggleBluetoothOnFailure()).isEqualTo(FIRST_BOOL);
+ assertThat(prefs.toBuilder().build().getToggleBluetoothOnFailure())
+ .isEqualTo(FIRST_BOOL);
+
+ Preferences prefs2 =
+ Preferences.builder().setToggleBluetoothOnFailure(SECOND_BOOL).build();
+ assertThat(prefs2.getToggleBluetoothOnFailure()).isEqualTo(SECOND_BOOL);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testBluetoothStateUsesPolling() {
+ Preferences prefs =
+ Preferences.builder().setBluetoothStateUsesPolling(FIRST_BOOL).build();
+ assertThat(prefs.getBluetoothStateUsesPolling()).isEqualTo(FIRST_BOOL);
+ assertThat(prefs.toBuilder().build().getBluetoothStateUsesPolling())
+ .isEqualTo(FIRST_BOOL);
+
+ Preferences prefs2 =
+ Preferences.builder().setBluetoothStateUsesPolling(SECOND_BOOL).build();
+ assertThat(prefs2.getBluetoothStateUsesPolling()).isEqualTo(SECOND_BOOL);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testEnableBrEdrHandover() {
+ Preferences prefs =
+ Preferences.builder().setEnableBrEdrHandover(FIRST_BOOL).build();
+ assertThat(prefs.getEnableBrEdrHandover()).isEqualTo(FIRST_BOOL);
+ assertThat(prefs.toBuilder().build().getEnableBrEdrHandover())
+ .isEqualTo(FIRST_BOOL);
+
+ Preferences prefs2 =
+ Preferences.builder().setEnableBrEdrHandover(SECOND_BOOL).build();
+ assertThat(prefs2.getEnableBrEdrHandover()).isEqualTo(SECOND_BOOL);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testWaitForUuidsAfterBonding() {
+ Preferences prefs =
+ Preferences.builder().setWaitForUuidsAfterBonding(FIRST_BOOL).build();
+ assertThat(prefs.getWaitForUuidsAfterBonding()).isEqualTo(FIRST_BOOL);
+ assertThat(prefs.toBuilder().build().getWaitForUuidsAfterBonding())
+ .isEqualTo(FIRST_BOOL);
+
+ Preferences prefs2 =
+ Preferences.builder().setWaitForUuidsAfterBonding(SECOND_BOOL).build();
+ assertThat(prefs2.getWaitForUuidsAfterBonding()).isEqualTo(SECOND_BOOL);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testReceiveUuidsAndBondedEventBeforeClose() {
+ Preferences prefs =
+ Preferences.builder().setReceiveUuidsAndBondedEventBeforeClose(FIRST_BOOL).build();
+ assertThat(prefs.getReceiveUuidsAndBondedEventBeforeClose()).isEqualTo(FIRST_BOOL);
+ assertThat(prefs.toBuilder().build().getReceiveUuidsAndBondedEventBeforeClose())
+ .isEqualTo(FIRST_BOOL);
+
+ Preferences prefs2 =
+ Preferences.builder().setReceiveUuidsAndBondedEventBeforeClose(SECOND_BOOL).build();
+ assertThat(prefs2.getReceiveUuidsAndBondedEventBeforeClose()).isEqualTo(SECOND_BOOL);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testRejectPhonebookAccess() {
+ Preferences prefs =
+ Preferences.builder().setRejectPhonebookAccess(FIRST_BOOL).build();
+ assertThat(prefs.getRejectPhonebookAccess()).isEqualTo(FIRST_BOOL);
+ assertThat(prefs.toBuilder().build().getRejectPhonebookAccess())
+ .isEqualTo(FIRST_BOOL);
+
+ Preferences prefs2 =
+ Preferences.builder().setRejectPhonebookAccess(SECOND_BOOL).build();
+ assertThat(prefs2.getRejectPhonebookAccess()).isEqualTo(SECOND_BOOL);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testRejectMessageAccess() {
+ Preferences prefs =
+ Preferences.builder().setRejectMessageAccess(FIRST_BOOL).build();
+ assertThat(prefs.getRejectMessageAccess()).isEqualTo(FIRST_BOOL);
+ assertThat(prefs.toBuilder().build().getRejectMessageAccess())
+ .isEqualTo(FIRST_BOOL);
+
+ Preferences prefs2 =
+ Preferences.builder().setRejectMessageAccess(SECOND_BOOL).build();
+ assertThat(prefs2.getRejectMessageAccess()).isEqualTo(SECOND_BOOL);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testRejectSimAccess() {
+ Preferences prefs =
+ Preferences.builder().setRejectSimAccess(FIRST_BOOL).build();
+ assertThat(prefs.getRejectSimAccess()).isEqualTo(FIRST_BOOL);
+ assertThat(prefs.toBuilder().build().getRejectSimAccess())
+ .isEqualTo(FIRST_BOOL);
+
+ Preferences prefs2 =
+ Preferences.builder().setRejectSimAccess(SECOND_BOOL).build();
+ assertThat(prefs2.getRejectSimAccess()).isEqualTo(SECOND_BOOL);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testSkipDisconnectingGattBeforeWritingAccountKey() {
+ Preferences prefs =
+ Preferences.builder().setSkipDisconnectingGattBeforeWritingAccountKey(FIRST_BOOL)
+ .build();
+ assertThat(prefs.getSkipDisconnectingGattBeforeWritingAccountKey()).isEqualTo(FIRST_BOOL);
+ assertThat(prefs.toBuilder().build().getSkipDisconnectingGattBeforeWritingAccountKey())
+ .isEqualTo(FIRST_BOOL);
+
+ Preferences prefs2 =
+ Preferences.builder().setSkipDisconnectingGattBeforeWritingAccountKey(SECOND_BOOL)
+ .build();
+ assertThat(prefs2.getSkipDisconnectingGattBeforeWritingAccountKey()).isEqualTo(SECOND_BOOL);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testMoreEventLogForQuality() {
+ Preferences prefs =
+ Preferences.builder().setMoreEventLogForQuality(FIRST_BOOL).build();
+ assertThat(prefs.getMoreEventLogForQuality()).isEqualTo(FIRST_BOOL);
+ assertThat(prefs.toBuilder().build().getMoreEventLogForQuality())
+ .isEqualTo(FIRST_BOOL);
+
+ Preferences prefs2 =
+ Preferences.builder().setMoreEventLogForQuality(SECOND_BOOL).build();
+ assertThat(prefs2.getMoreEventLogForQuality()).isEqualTo(SECOND_BOOL);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testRetryGattConnectionAndSecretHandshake() {
+ Preferences prefs =
+ Preferences.builder().setRetryGattConnectionAndSecretHandshake(FIRST_BOOL).build();
+ assertThat(prefs.getRetryGattConnectionAndSecretHandshake()).isEqualTo(FIRST_BOOL);
+ assertThat(prefs.toBuilder().build().getRetryGattConnectionAndSecretHandshake())
+ .isEqualTo(FIRST_BOOL);
+
+ Preferences prefs2 =
+ Preferences.builder().setRetryGattConnectionAndSecretHandshake(SECOND_BOOL).build();
+ assertThat(prefs2.getRetryGattConnectionAndSecretHandshake()).isEqualTo(SECOND_BOOL);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testRetrySecretHandshakeTimeout() {
+ Preferences prefs =
+ Preferences.builder().setRetrySecretHandshakeTimeout(FIRST_BOOL).build();
+ assertThat(prefs.getRetrySecretHandshakeTimeout()).isEqualTo(FIRST_BOOL);
+ assertThat(prefs.toBuilder().build().getRetrySecretHandshakeTimeout())
+ .isEqualTo(FIRST_BOOL);
+
+ Preferences prefs2 =
+ Preferences.builder().setRetrySecretHandshakeTimeout(SECOND_BOOL).build();
+ assertThat(prefs2.getRetrySecretHandshakeTimeout()).isEqualTo(SECOND_BOOL);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testLogUserManualRetry() {
+ Preferences prefs =
+ Preferences.builder().setLogUserManualRetry(FIRST_BOOL).build();
+ assertThat(prefs.getLogUserManualRetry()).isEqualTo(FIRST_BOOL);
+ assertThat(prefs.toBuilder().build().getLogUserManualRetry())
+ .isEqualTo(FIRST_BOOL);
+
+ Preferences prefs2 =
+ Preferences.builder().setLogUserManualRetry(SECOND_BOOL).build();
+ assertThat(prefs2.getLogUserManualRetry()).isEqualTo(SECOND_BOOL);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testIsDeviceFinishCheckAddressFromCache() {
+ Preferences prefs =
+ Preferences.builder().setIsDeviceFinishCheckAddressFromCache(FIRST_BOOL).build();
+ assertThat(prefs.getIsDeviceFinishCheckAddressFromCache()).isEqualTo(FIRST_BOOL);
+ assertThat(prefs.toBuilder().build().getIsDeviceFinishCheckAddressFromCache())
+ .isEqualTo(FIRST_BOOL);
+
+ Preferences prefs2 =
+ Preferences.builder().setIsDeviceFinishCheckAddressFromCache(SECOND_BOOL).build();
+ assertThat(prefs2.getIsDeviceFinishCheckAddressFromCache()).isEqualTo(SECOND_BOOL);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testLogPairWithCachedModelId() {
+ Preferences prefs =
+ Preferences.builder().setLogPairWithCachedModelId(FIRST_BOOL).build();
+ assertThat(prefs.getLogPairWithCachedModelId()).isEqualTo(FIRST_BOOL);
+ assertThat(prefs.toBuilder().build().getLogPairWithCachedModelId())
+ .isEqualTo(FIRST_BOOL);
+
+ Preferences prefs2 =
+ Preferences.builder().setLogPairWithCachedModelId(SECOND_BOOL).build();
+ assertThat(prefs2.getLogPairWithCachedModelId()).isEqualTo(SECOND_BOOL);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testDirectConnectProfileIfModelIdInCache() {
+ Preferences prefs =
+ Preferences.builder().setDirectConnectProfileIfModelIdInCache(FIRST_BOOL).build();
+ assertThat(prefs.getDirectConnectProfileIfModelIdInCache()).isEqualTo(FIRST_BOOL);
+ assertThat(prefs.toBuilder().build().getDirectConnectProfileIfModelIdInCache())
+ .isEqualTo(FIRST_BOOL);
+
+ Preferences prefs2 =
+ Preferences.builder().setDirectConnectProfileIfModelIdInCache(SECOND_BOOL).build();
+ assertThat(prefs2.getDirectConnectProfileIfModelIdInCache()).isEqualTo(SECOND_BOOL);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testAcceptPasskey() {
+ Preferences prefs =
+ Preferences.builder().setAcceptPasskey(FIRST_BOOL).build();
+ assertThat(prefs.getAcceptPasskey()).isEqualTo(FIRST_BOOL);
+ assertThat(prefs.toBuilder().build().getAcceptPasskey())
+ .isEqualTo(FIRST_BOOL);
+
+ Preferences prefs2 =
+ Preferences.builder().setAcceptPasskey(SECOND_BOOL).build();
+ assertThat(prefs2.getAcceptPasskey()).isEqualTo(SECOND_BOOL);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testProviderInitiatesBondingIfSupported() {
+ Preferences prefs =
+ Preferences.builder().setProviderInitiatesBondingIfSupported(FIRST_BOOL).build();
+ assertThat(prefs.getProviderInitiatesBondingIfSupported()).isEqualTo(FIRST_BOOL);
+ assertThat(prefs.toBuilder().build().getProviderInitiatesBondingIfSupported())
+ .isEqualTo(FIRST_BOOL);
+
+ Preferences prefs2 =
+ Preferences.builder().setProviderInitiatesBondingIfSupported(SECOND_BOOL).build();
+ assertThat(prefs2.getProviderInitiatesBondingIfSupported()).isEqualTo(SECOND_BOOL);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testAttemptDirectConnectionWhenPreviouslyBonded() {
+ Preferences prefs =
+ Preferences.builder()
+ .setAttemptDirectConnectionWhenPreviouslyBonded(FIRST_BOOL).build();
+ assertThat(prefs.getAttemptDirectConnectionWhenPreviouslyBonded()).isEqualTo(FIRST_BOOL);
+ assertThat(prefs.toBuilder().build().getAttemptDirectConnectionWhenPreviouslyBonded())
+ .isEqualTo(FIRST_BOOL);
+
+ Preferences prefs2 =
+ Preferences.builder()
+ .setAttemptDirectConnectionWhenPreviouslyBonded(SECOND_BOOL).build();
+ assertThat(prefs2.getAttemptDirectConnectionWhenPreviouslyBonded()).isEqualTo(SECOND_BOOL);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testAutomaticallyReconnectGattWhenNeeded() {
+ Preferences prefs =
+ Preferences.builder().setAutomaticallyReconnectGattWhenNeeded(FIRST_BOOL).build();
+ assertThat(prefs.getAutomaticallyReconnectGattWhenNeeded()).isEqualTo(FIRST_BOOL);
+ assertThat(prefs.toBuilder().build().getAutomaticallyReconnectGattWhenNeeded())
+ .isEqualTo(FIRST_BOOL);
+
+ Preferences prefs2 =
+ Preferences.builder().setAutomaticallyReconnectGattWhenNeeded(SECOND_BOOL).build();
+ assertThat(prefs2.getAutomaticallyReconnectGattWhenNeeded()).isEqualTo(SECOND_BOOL);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testSkipConnectingProfiles() {
+ Preferences prefs =
+ Preferences.builder().setSkipConnectingProfiles(FIRST_BOOL).build();
+ assertThat(prefs.getSkipConnectingProfiles()).isEqualTo(FIRST_BOOL);
+ assertThat(prefs.toBuilder().build().getSkipConnectingProfiles())
+ .isEqualTo(FIRST_BOOL);
+
+ Preferences prefs2 =
+ Preferences.builder().setSkipConnectingProfiles(SECOND_BOOL).build();
+ assertThat(prefs2.getSkipConnectingProfiles()).isEqualTo(SECOND_BOOL);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testIgnoreUuidTimeoutAfterBonded() {
+ Preferences prefs =
+ Preferences.builder().setIgnoreUuidTimeoutAfterBonded(FIRST_BOOL).build();
+ assertThat(prefs.getIgnoreUuidTimeoutAfterBonded()).isEqualTo(FIRST_BOOL);
+ assertThat(prefs.toBuilder().build().getIgnoreUuidTimeoutAfterBonded())
+ .isEqualTo(FIRST_BOOL);
+
+ Preferences prefs2 =
+ Preferences.builder().setIgnoreUuidTimeoutAfterBonded(SECOND_BOOL).build();
+ assertThat(prefs2.getIgnoreUuidTimeoutAfterBonded()).isEqualTo(SECOND_BOOL);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testSpecifyCreateBondTransportType() {
+ Preferences prefs =
+ Preferences.builder().setSpecifyCreateBondTransportType(FIRST_BOOL).build();
+ assertThat(prefs.getSpecifyCreateBondTransportType()).isEqualTo(FIRST_BOOL);
+ assertThat(prefs.toBuilder().build().getSpecifyCreateBondTransportType())
+ .isEqualTo(FIRST_BOOL);
+
+ Preferences prefs2 =
+ Preferences.builder().setSpecifyCreateBondTransportType(SECOND_BOOL).build();
+ assertThat(prefs2.getSpecifyCreateBondTransportType()).isEqualTo(SECOND_BOOL);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testIncreaseIntentFilterPriority() {
+ Preferences prefs =
+ Preferences.builder().setIncreaseIntentFilterPriority(FIRST_BOOL).build();
+ assertThat(prefs.getIncreaseIntentFilterPriority()).isEqualTo(FIRST_BOOL);
+ assertThat(prefs.toBuilder().build().getIncreaseIntentFilterPriority())
+ .isEqualTo(FIRST_BOOL);
+
+ Preferences prefs2 =
+ Preferences.builder().setIncreaseIntentFilterPriority(SECOND_BOOL).build();
+ assertThat(prefs2.getIncreaseIntentFilterPriority()).isEqualTo(SECOND_BOOL);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testEvaluatePerformance() {
+ Preferences prefs =
+ Preferences.builder().setEvaluatePerformance(FIRST_BOOL).build();
+ assertThat(prefs.getEvaluatePerformance()).isEqualTo(FIRST_BOOL);
+ assertThat(prefs.toBuilder().build().getEvaluatePerformance())
+ .isEqualTo(FIRST_BOOL);
+
+ Preferences prefs2 =
+ Preferences.builder().setEvaluatePerformance(SECOND_BOOL).build();
+ assertThat(prefs2.getEvaluatePerformance()).isEqualTo(SECOND_BOOL);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testEnableNamingCharacteristic() {
+ Preferences prefs =
+ Preferences.builder().setEnableNamingCharacteristic(FIRST_BOOL).build();
+ assertThat(prefs.getEnableNamingCharacteristic()).isEqualTo(FIRST_BOOL);
+ assertThat(prefs.toBuilder().build().getEnableNamingCharacteristic())
+ .isEqualTo(FIRST_BOOL);
+
+ Preferences prefs2 =
+ Preferences.builder().setEnableNamingCharacteristic(SECOND_BOOL).build();
+ assertThat(prefs2.getEnableNamingCharacteristic()).isEqualTo(SECOND_BOOL);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testEnableFirmwareVersionCharacteristic() {
+ Preferences prefs =
+ Preferences.builder().setEnableFirmwareVersionCharacteristic(FIRST_BOOL).build();
+ assertThat(prefs.getEnableFirmwareVersionCharacteristic()).isEqualTo(FIRST_BOOL);
+ assertThat(prefs.toBuilder().build().getEnableFirmwareVersionCharacteristic())
+ .isEqualTo(FIRST_BOOL);
+
+ Preferences prefs2 =
+ Preferences.builder().setEnableFirmwareVersionCharacteristic(SECOND_BOOL).build();
+ assertThat(prefs2.getEnableFirmwareVersionCharacteristic()).isEqualTo(SECOND_BOOL);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testKeepSameAccountKeyWrite() {
+ Preferences prefs =
+ Preferences.builder().setKeepSameAccountKeyWrite(FIRST_BOOL).build();
+ assertThat(prefs.getKeepSameAccountKeyWrite()).isEqualTo(FIRST_BOOL);
+ assertThat(prefs.toBuilder().build().getKeepSameAccountKeyWrite())
+ .isEqualTo(FIRST_BOOL);
+
+ Preferences prefs2 =
+ Preferences.builder().setKeepSameAccountKeyWrite(SECOND_BOOL).build();
+ assertThat(prefs2.getKeepSameAccountKeyWrite()).isEqualTo(SECOND_BOOL);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testIsRetroactivePairing() {
+ Preferences prefs =
+ Preferences.builder().setIsRetroactivePairing(FIRST_BOOL).build();
+ assertThat(prefs.getIsRetroactivePairing()).isEqualTo(FIRST_BOOL);
+ assertThat(prefs.toBuilder().build().getIsRetroactivePairing())
+ .isEqualTo(FIRST_BOOL);
+
+ Preferences prefs2 =
+ Preferences.builder().setIsRetroactivePairing(SECOND_BOOL).build();
+ assertThat(prefs2.getIsRetroactivePairing()).isEqualTo(SECOND_BOOL);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testSupportHidDevice() {
+ Preferences prefs =
+ Preferences.builder().setSupportHidDevice(FIRST_BOOL).build();
+ assertThat(prefs.getSupportHidDevice()).isEqualTo(FIRST_BOOL);
+ assertThat(prefs.toBuilder().build().getSupportHidDevice())
+ .isEqualTo(FIRST_BOOL);
+
+ Preferences prefs2 =
+ Preferences.builder().setSupportHidDevice(SECOND_BOOL).build();
+ assertThat(prefs2.getSupportHidDevice()).isEqualTo(SECOND_BOOL);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testEnablePairingWhileDirectlyConnecting() {
+ Preferences prefs =
+ Preferences.builder().setEnablePairingWhileDirectlyConnecting(FIRST_BOOL).build();
+ assertThat(prefs.getEnablePairingWhileDirectlyConnecting()).isEqualTo(FIRST_BOOL);
+ assertThat(prefs.toBuilder().build().getEnablePairingWhileDirectlyConnecting())
+ .isEqualTo(FIRST_BOOL);
+
+ Preferences prefs2 =
+ Preferences.builder().setEnablePairingWhileDirectlyConnecting(SECOND_BOOL).build();
+ assertThat(prefs2.getEnablePairingWhileDirectlyConnecting()).isEqualTo(SECOND_BOOL);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testAcceptConsentForFastPairOne() {
+ Preferences prefs =
+ Preferences.builder().setAcceptConsentForFastPairOne(FIRST_BOOL).build();
+ assertThat(prefs.getAcceptConsentForFastPairOne()).isEqualTo(FIRST_BOOL);
+ assertThat(prefs.toBuilder().build().getAcceptConsentForFastPairOne())
+ .isEqualTo(FIRST_BOOL);
+
+ Preferences prefs2 =
+ Preferences.builder().setAcceptConsentForFastPairOne(SECOND_BOOL).build();
+ assertThat(prefs2.getAcceptConsentForFastPairOne()).isEqualTo(SECOND_BOOL);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testEnable128BitCustomGattCharacteristicsId() {
+ Preferences prefs =
+ Preferences.builder().setEnable128BitCustomGattCharacteristicsId(FIRST_BOOL)
+ .build();
+ assertThat(prefs.getEnable128BitCustomGattCharacteristicsId()).isEqualTo(FIRST_BOOL);
+ assertThat(prefs.toBuilder().build().getEnable128BitCustomGattCharacteristicsId())
+ .isEqualTo(FIRST_BOOL);
+
+ Preferences prefs2 =
+ Preferences.builder().setEnable128BitCustomGattCharacteristicsId(SECOND_BOOL)
+ .build();
+ assertThat(prefs2.getEnable128BitCustomGattCharacteristicsId()).isEqualTo(SECOND_BOOL);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testEnableSendExceptionStepToValidator() {
+ Preferences prefs =
+ Preferences.builder().setEnableSendExceptionStepToValidator(FIRST_BOOL).build();
+ assertThat(prefs.getEnableSendExceptionStepToValidator()).isEqualTo(FIRST_BOOL);
+ assertThat(prefs.toBuilder().build().getEnableSendExceptionStepToValidator())
+ .isEqualTo(FIRST_BOOL);
+
+ Preferences prefs2 =
+ Preferences.builder().setEnableSendExceptionStepToValidator(SECOND_BOOL).build();
+ assertThat(prefs2.getEnableSendExceptionStepToValidator()).isEqualTo(SECOND_BOOL);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testEnableAdditionalDataTypeWhenActionOverBle() {
+ Preferences prefs =
+ Preferences.builder().setEnableAdditionalDataTypeWhenActionOverBle(FIRST_BOOL)
+ .build();
+ assertThat(prefs.getEnableAdditionalDataTypeWhenActionOverBle()).isEqualTo(FIRST_BOOL);
+ assertThat(prefs.toBuilder().build().getEnableAdditionalDataTypeWhenActionOverBle())
+ .isEqualTo(FIRST_BOOL);
+
+ Preferences prefs2 =
+ Preferences.builder().setEnableAdditionalDataTypeWhenActionOverBle(SECOND_BOOL)
+ .build();
+ assertThat(prefs2.getEnableAdditionalDataTypeWhenActionOverBle()).isEqualTo(SECOND_BOOL);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testCheckBondStateWhenSkipConnectingProfiles() {
+ Preferences prefs =
+ Preferences.builder().setCheckBondStateWhenSkipConnectingProfiles(FIRST_BOOL)
+ .build();
+ assertThat(prefs.getCheckBondStateWhenSkipConnectingProfiles()).isEqualTo(FIRST_BOOL);
+ assertThat(prefs.toBuilder().build().getCheckBondStateWhenSkipConnectingProfiles())
+ .isEqualTo(FIRST_BOOL);
+
+ Preferences prefs2 =
+ Preferences.builder().setCheckBondStateWhenSkipConnectingProfiles(SECOND_BOOL)
+ .build();
+ assertThat(prefs2.getCheckBondStateWhenSkipConnectingProfiles()).isEqualTo(SECOND_BOOL);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testHandlePasskeyConfirmationByUi() {
+ Preferences prefs =
+ Preferences.builder().setHandlePasskeyConfirmationByUi(FIRST_BOOL).build();
+ assertThat(prefs.getHandlePasskeyConfirmationByUi()).isEqualTo(FIRST_BOOL);
+ assertThat(prefs.toBuilder().build().getHandlePasskeyConfirmationByUi())
+ .isEqualTo(FIRST_BOOL);
+
+ Preferences prefs2 =
+ Preferences.builder().setHandlePasskeyConfirmationByUi(SECOND_BOOL).build();
+ assertThat(prefs2.getHandlePasskeyConfirmationByUi()).isEqualTo(SECOND_BOOL);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testEnablePairFlowShowUiWithoutProfileConnection() {
+ Preferences prefs =
+ Preferences.builder().setEnablePairFlowShowUiWithoutProfileConnection(FIRST_BOOL)
+ .build();
+ assertThat(prefs.getEnablePairFlowShowUiWithoutProfileConnection()).isEqualTo(FIRST_BOOL);
+ assertThat(prefs.toBuilder().build().getEnablePairFlowShowUiWithoutProfileConnection())
+ .isEqualTo(FIRST_BOOL);
+
+ Preferences prefs2 =
+ Preferences.builder().setEnablePairFlowShowUiWithoutProfileConnection(SECOND_BOOL)
+ .build();
+ assertThat(prefs2.getEnablePairFlowShowUiWithoutProfileConnection()).isEqualTo(SECOND_BOOL);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testBrHandoverDataCharacteristicId() {
+ Preferences prefs =
+ Preferences.builder().setBrHandoverDataCharacteristicId(FIRST_SHORT).build();
+ assertThat(prefs.getBrHandoverDataCharacteristicId()).isEqualTo(FIRST_SHORT);
+ assertThat(prefs.toBuilder().build().getBrHandoverDataCharacteristicId())
+ .isEqualTo(FIRST_SHORT);
+
+ Preferences prefs2 =
+ Preferences.builder().setBrHandoverDataCharacteristicId(SECOND_SHORT).build();
+ assertThat(prefs2.getBrHandoverDataCharacteristicId()).isEqualTo(SECOND_SHORT);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testBluetoothSigDataCharacteristicId() {
+ Preferences prefs =
+ Preferences.builder().setBluetoothSigDataCharacteristicId(FIRST_SHORT).build();
+ assertThat(prefs.getBluetoothSigDataCharacteristicId()).isEqualTo(FIRST_SHORT);
+ assertThat(prefs.toBuilder().build().getBluetoothSigDataCharacteristicId())
+ .isEqualTo(FIRST_SHORT);
+
+ Preferences prefs2 =
+ Preferences.builder().setBluetoothSigDataCharacteristicId(SECOND_SHORT).build();
+ assertThat(prefs2.getBluetoothSigDataCharacteristicId()).isEqualTo(SECOND_SHORT);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testFirmwareVersionCharacteristicId() {
+ Preferences prefs =
+ Preferences.builder().setFirmwareVersionCharacteristicId(FIRST_SHORT).build();
+ assertThat(prefs.getFirmwareVersionCharacteristicId()).isEqualTo(FIRST_SHORT);
+ assertThat(prefs.toBuilder().build().getFirmwareVersionCharacteristicId())
+ .isEqualTo(FIRST_SHORT);
+
+ Preferences prefs2 =
+ Preferences.builder().setFirmwareVersionCharacteristicId(SECOND_SHORT).build();
+ assertThat(prefs2.getFirmwareVersionCharacteristicId()).isEqualTo(SECOND_SHORT);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testBrTransportBlockDataDescriptorId() {
+ Preferences prefs =
+ Preferences.builder().setBrTransportBlockDataDescriptorId(FIRST_SHORT).build();
+ assertThat(prefs.getBrTransportBlockDataDescriptorId()).isEqualTo(FIRST_SHORT);
+ assertThat(prefs.toBuilder().build().getBrTransportBlockDataDescriptorId())
+ .isEqualTo(FIRST_SHORT);
+
+ Preferences prefs2 =
+ Preferences.builder().setBrTransportBlockDataDescriptorId(SECOND_SHORT).build();
+ assertThat(prefs2.getBrTransportBlockDataDescriptorId()).isEqualTo(SECOND_SHORT);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testGattConnectShortTimeoutMs() {
+ Preferences prefs =
+ Preferences.builder().setGattConnectShortTimeoutMs(FIRST_LONG).build();
+ assertThat(prefs.getGattConnectShortTimeoutMs()).isEqualTo(FIRST_LONG);
+ assertThat(prefs.toBuilder().build().getGattConnectShortTimeoutMs())
+ .isEqualTo(FIRST_LONG);
+
+ Preferences prefs2 =
+ Preferences.builder().setGattConnectShortTimeoutMs(SECOND_LONG).build();
+ assertThat(prefs2.getGattConnectShortTimeoutMs()).isEqualTo(SECOND_LONG);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testGattConnectLongTimeoutMs() {
+ Preferences prefs =
+ Preferences.builder().setGattConnectLongTimeoutMs(FIRST_LONG).build();
+ assertThat(prefs.getGattConnectLongTimeoutMs()).isEqualTo(FIRST_LONG);
+ assertThat(prefs.toBuilder().build().getGattConnectLongTimeoutMs())
+ .isEqualTo(FIRST_LONG);
+
+ Preferences prefs2 =
+ Preferences.builder().setGattConnectLongTimeoutMs(SECOND_LONG).build();
+ assertThat(prefs2.getGattConnectLongTimeoutMs()).isEqualTo(SECOND_LONG);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testGattConnectShortTimeoutRetryMaxSpentTimeMs() {
+ Preferences prefs =
+ Preferences.builder().setGattConnectShortTimeoutRetryMaxSpentTimeMs(FIRST_LONG)
+ .build();
+ assertThat(prefs.getGattConnectShortTimeoutRetryMaxSpentTimeMs()).isEqualTo(FIRST_LONG);
+ assertThat(prefs.toBuilder().build().getGattConnectShortTimeoutRetryMaxSpentTimeMs())
+ .isEqualTo(FIRST_LONG);
+
+ Preferences prefs2 =
+ Preferences.builder().setGattConnectShortTimeoutRetryMaxSpentTimeMs(SECOND_LONG)
+ .build();
+ assertThat(prefs2.getGattConnectShortTimeoutRetryMaxSpentTimeMs()).isEqualTo(SECOND_LONG);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testAddressRotateRetryMaxSpentTimeMs() {
+ Preferences prefs =
+ Preferences.builder().setAddressRotateRetryMaxSpentTimeMs(FIRST_LONG).build();
+ assertThat(prefs.getAddressRotateRetryMaxSpentTimeMs()).isEqualTo(FIRST_LONG);
+ assertThat(prefs.toBuilder().build().getAddressRotateRetryMaxSpentTimeMs())
+ .isEqualTo(FIRST_LONG);
+
+ Preferences prefs2 =
+ Preferences.builder().setAddressRotateRetryMaxSpentTimeMs(SECOND_LONG).build();
+ assertThat(prefs2.getAddressRotateRetryMaxSpentTimeMs()).isEqualTo(SECOND_LONG);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testPairingRetryDelayMs() {
+ Preferences prefs =
+ Preferences.builder().setPairingRetryDelayMs(FIRST_LONG).build();
+ assertThat(prefs.getPairingRetryDelayMs()).isEqualTo(FIRST_LONG);
+ assertThat(prefs.toBuilder().build().getPairingRetryDelayMs())
+ .isEqualTo(FIRST_LONG);
+
+ Preferences prefs2 =
+ Preferences.builder().setPairingRetryDelayMs(SECOND_LONG).build();
+ assertThat(prefs2.getPairingRetryDelayMs()).isEqualTo(SECOND_LONG);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testSecretHandshakeShortTimeoutMs() {
+ Preferences prefs =
+ Preferences.builder().setSecretHandshakeShortTimeoutMs(FIRST_LONG).build();
+ assertThat(prefs.getSecretHandshakeShortTimeoutMs()).isEqualTo(FIRST_LONG);
+ assertThat(prefs.toBuilder().build().getSecretHandshakeShortTimeoutMs())
+ .isEqualTo(FIRST_LONG);
+
+ Preferences prefs2 =
+ Preferences.builder().setSecretHandshakeShortTimeoutMs(SECOND_LONG).build();
+ assertThat(prefs2.getSecretHandshakeShortTimeoutMs()).isEqualTo(SECOND_LONG);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testSecretHandshakeLongTimeoutMs() {
+ Preferences prefs =
+ Preferences.builder().setSecretHandshakeLongTimeoutMs(FIRST_LONG).build();
+ assertThat(prefs.getSecretHandshakeLongTimeoutMs()).isEqualTo(FIRST_LONG);
+ assertThat(prefs.toBuilder().build().getSecretHandshakeLongTimeoutMs())
+ .isEqualTo(FIRST_LONG);
+
+ Preferences prefs2 =
+ Preferences.builder().setSecretHandshakeLongTimeoutMs(SECOND_LONG).build();
+ assertThat(prefs2.getSecretHandshakeLongTimeoutMs()).isEqualTo(SECOND_LONG);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testSecretHandshakeShortTimeoutRetryMaxSpentTimeMs() {
+ Preferences prefs =
+ Preferences.builder().setSecretHandshakeShortTimeoutRetryMaxSpentTimeMs(FIRST_LONG)
+ .build();
+ assertThat(prefs.getSecretHandshakeShortTimeoutRetryMaxSpentTimeMs()).isEqualTo(FIRST_LONG);
+ assertThat(prefs.toBuilder().build().getSecretHandshakeShortTimeoutRetryMaxSpentTimeMs())
+ .isEqualTo(FIRST_LONG);
+
+ Preferences prefs2 =
+ Preferences.builder().setSecretHandshakeShortTimeoutRetryMaxSpentTimeMs(SECOND_LONG)
+ .build();
+ assertThat(prefs2.getSecretHandshakeShortTimeoutRetryMaxSpentTimeMs())
+ .isEqualTo(SECOND_LONG);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testSecretHandshakeLongTimeoutRetryMaxSpentTimeMs() {
+ Preferences prefs =
+ Preferences.builder().setSecretHandshakeLongTimeoutRetryMaxSpentTimeMs(FIRST_LONG)
+ .build();
+ assertThat(prefs.getSecretHandshakeLongTimeoutRetryMaxSpentTimeMs()).isEqualTo(FIRST_LONG);
+ assertThat(prefs.toBuilder().build().getSecretHandshakeLongTimeoutRetryMaxSpentTimeMs())
+ .isEqualTo(FIRST_LONG);
+
+ Preferences prefs2 =
+ Preferences.builder().setSecretHandshakeLongTimeoutRetryMaxSpentTimeMs(SECOND_LONG)
+ .build();
+ assertThat(prefs2.getSecretHandshakeLongTimeoutRetryMaxSpentTimeMs())
+ .isEqualTo(SECOND_LONG);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testSecretHandshakeRetryAttempts() {
+ Preferences prefs =
+ Preferences.builder().setSecretHandshakeRetryAttempts(FIRST_LONG).build();
+ assertThat(prefs.getSecretHandshakeRetryAttempts()).isEqualTo(FIRST_LONG);
+ assertThat(prefs.toBuilder().build().getSecretHandshakeRetryAttempts())
+ .isEqualTo(FIRST_LONG);
+
+ Preferences prefs2 =
+ Preferences.builder().setSecretHandshakeRetryAttempts(SECOND_LONG).build();
+ assertThat(prefs2.getSecretHandshakeRetryAttempts()).isEqualTo(SECOND_LONG);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testSecretHandshakeRetryGattConnectionMaxSpentTimeMs() {
+ Preferences prefs =
+ Preferences.builder()
+ .setSecretHandshakeRetryGattConnectionMaxSpentTimeMs(FIRST_LONG).build();
+ assertThat(prefs.getSecretHandshakeRetryGattConnectionMaxSpentTimeMs())
+ .isEqualTo(FIRST_LONG);
+ assertThat(prefs.toBuilder().build().getSecretHandshakeRetryGattConnectionMaxSpentTimeMs())
+ .isEqualTo(FIRST_LONG);
+
+ Preferences prefs2 =
+ Preferences.builder().setSecretHandshakeRetryGattConnectionMaxSpentTimeMs(
+ SECOND_LONG).build();
+ assertThat(prefs2.getSecretHandshakeRetryGattConnectionMaxSpentTimeMs())
+ .isEqualTo(SECOND_LONG);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testSignalLostRetryMaxSpentTimeMs() {
+ Preferences prefs =
+ Preferences.builder().setSignalLostRetryMaxSpentTimeMs(FIRST_LONG).build();
+ assertThat(prefs.getSignalLostRetryMaxSpentTimeMs()).isEqualTo(FIRST_LONG);
+ assertThat(prefs.toBuilder().build().getSignalLostRetryMaxSpentTimeMs())
+ .isEqualTo(FIRST_LONG);
+
+ Preferences prefs2 =
+ Preferences.builder().setSignalLostRetryMaxSpentTimeMs(SECOND_LONG).build();
+ assertThat(prefs2.getSignalLostRetryMaxSpentTimeMs()).isEqualTo(SECOND_LONG);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testCachedDeviceAddress() {
+ Preferences prefs =
+ Preferences.builder().setCachedDeviceAddress(FIRST_STRING).build();
+ assertThat(prefs.getCachedDeviceAddress()).isEqualTo(FIRST_STRING);
+ assertThat(prefs.toBuilder().build().getCachedDeviceAddress())
+ .isEqualTo(FIRST_STRING);
+
+ Preferences prefs2 =
+ Preferences.builder().setCachedDeviceAddress(SECOND_STRING).build();
+ assertThat(prefs2.getCachedDeviceAddress()).isEqualTo(SECOND_STRING);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testPossibleCachedDeviceAddress() {
+ Preferences prefs =
+ Preferences.builder().setPossibleCachedDeviceAddress(FIRST_STRING).build();
+ assertThat(prefs.getPossibleCachedDeviceAddress()).isEqualTo(FIRST_STRING);
+ assertThat(prefs.toBuilder().build().getPossibleCachedDeviceAddress())
+ .isEqualTo(FIRST_STRING);
+
+ Preferences prefs2 =
+ Preferences.builder().setPossibleCachedDeviceAddress(SECOND_STRING).build();
+ assertThat(prefs2.getPossibleCachedDeviceAddress()).isEqualTo(SECOND_STRING);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testSupportedProfileUuids() {
+ Preferences prefs =
+ Preferences.builder().setSupportedProfileUuids(FIRST_BYTES).build();
+ assertThat(prefs.getSupportedProfileUuids()).isEqualTo(FIRST_BYTES);
+ assertThat(prefs.toBuilder().build().getSupportedProfileUuids())
+ .isEqualTo(FIRST_BYTES);
+
+ Preferences prefs2 =
+ Preferences.builder().setSupportedProfileUuids(SECOND_BYTES).build();
+ assertThat(prefs2.getSupportedProfileUuids()).isEqualTo(SECOND_BYTES);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testGattConnectionAndSecretHandshakeNoRetryGattError() {
+ Preferences prefs =
+ Preferences.builder().setGattConnectionAndSecretHandshakeNoRetryGattError(
+ FIRST_INT_SETS).build();
+ assertThat(prefs.getGattConnectionAndSecretHandshakeNoRetryGattError())
+ .isEqualTo(FIRST_INT_SETS);
+ assertThat(prefs.toBuilder().build().getGattConnectionAndSecretHandshakeNoRetryGattError())
+ .isEqualTo(FIRST_INT_SETS);
+
+ Preferences prefs2 =
+ Preferences.builder().setGattConnectionAndSecretHandshakeNoRetryGattError(
+ SECOND_INT_SETS).build();
+ assertThat(prefs2.getGattConnectionAndSecretHandshakeNoRetryGattError())
+ .isEqualTo(SECOND_INT_SETS);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testExtraLoggingInformation() {
+ Preferences prefs =
+ Preferences.builder().setExtraLoggingInformation(FIRST_EXTRA_LOGGING_INFO).build();
+ assertThat(prefs.getExtraLoggingInformation()).isEqualTo(FIRST_EXTRA_LOGGING_INFO);
+ assertThat(prefs.toBuilder().build().getExtraLoggingInformation())
+ .isEqualTo(FIRST_EXTRA_LOGGING_INFO);
+
+ Preferences prefs2 =
+ Preferences.builder().setExtraLoggingInformation(SECOND_EXTRA_LOGGING_INFO).build();
+ assertThat(prefs2.getExtraLoggingInformation()).isEqualTo(SECOND_EXTRA_LOGGING_INFO);
+ }
+}
diff --git a/nearby/tests/unit/src/com/android/server/nearby/fastpair/FastPairManagerTest.java b/nearby/tests/unit/src/com/android/server/nearby/fastpair/FastPairManagerTest.java
index f061115..26d1847 100644
--- a/nearby/tests/unit/src/com/android/server/nearby/fastpair/FastPairManagerTest.java
+++ b/nearby/tests/unit/src/com/android/server/nearby/fastpair/FastPairManagerTest.java
@@ -19,10 +19,12 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
import android.content.Context;
import androidx.test.filters.SdkSuppress;
+import androidx.test.platform.app.InstrumentationRegistry;
import com.android.server.nearby.common.locator.LocatorContextWrapper;
@@ -40,8 +42,11 @@
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
+
mLocatorContextWrapper = new LocatorContextWrapper(mContext);
mFastPairManager = new FastPairManager(mLocatorContextWrapper);
+ when(mContext.getContentResolver()).thenReturn(
+ InstrumentationRegistry.getInstrumentation().getContext().getContentResolver());
}
@Test
diff --git a/nearby/tests/unit/src/com/android/server/nearby/provider/UtilsTest.java b/nearby/tests/unit/src/com/android/server/nearby/provider/UtilsTest.java
new file mode 100644
index 0000000..08a3c7c
--- /dev/null
+++ b/nearby/tests/unit/src/com/android/server/nearby/provider/UtilsTest.java
@@ -0,0 +1,733 @@
+/*
+ * 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 com.google.common.truth.Truth.assertThat;
+
+import android.accounts.Account;
+import android.nearby.aidl.FastPairAccountKeyDeviceMetadataParcel;
+import android.nearby.aidl.FastPairAntispoofkeyDeviceMetadataParcel;
+import android.nearby.aidl.FastPairDeviceMetadataParcel;
+import android.nearby.aidl.FastPairDiscoveryItemParcel;
+import android.nearby.aidl.FastPairEligibleAccountParcel;
+
+import androidx.test.filters.SdkSuppress;
+
+import com.android.server.nearby.fastpair.footprint.FastPairUploadInfo;
+
+import com.google.protobuf.ByteString;
+
+import org.junit.Test;
+
+import java.util.List;
+
+import service.proto.Cache;
+import service.proto.Data;
+import service.proto.FastPairString.FastPairStrings;
+import service.proto.Rpcs;
+
+public class UtilsTest {
+
+ private static final String ASSISTANT_SETUP_HALFSHEET = "ASSISTANT_SETUP_HALFSHEET";
+ private static final String ASSISTANT_SETUP_NOTIFICATION = "ASSISTANT_SETUP_NOTIFICATION";
+ private static final int BLE_TX_POWER = 5;
+ private static final String CONFIRM_PIN_DESCRIPTION = "CONFIRM_PIN_DESCRIPTION";
+ private static final String CONFIRM_PIN_TITLE = "CONFIRM_PIN_TITLE";
+ private static final String CONNECT_SUCCESS_COMPANION_APP_INSTALLED =
+ "CONNECT_SUCCESS_COMPANION_APP_INSTALLED";
+ private static final String CONNECT_SUCCESS_COMPANION_APP_NOT_INSTALLED =
+ "CONNECT_SUCCESS_COMPANION_APP_NOT_INSTALLED";
+ private static final int DEVICE_TYPE = 1;
+ private static final String DOWNLOAD_COMPANION_APP_DESCRIPTION =
+ "DOWNLOAD_COMPANION_APP_DESCRIPTION";
+ private static final Account ELIGIBLE_ACCOUNT_1 = new Account("abc@google.com", "type1");
+ private static final String FAIL_CONNECT_GOTO_SETTINGS_DESCRIPTION =
+ "FAIL_CONNECT_GOTO_SETTINGS_DESCRIPTION";
+ private static final String FAST_PAIR_TV_CONNECT_DEVICE_NO_ACCOUNT_DESCRIPTION =
+ "FAST_PAIR_TV_CONNECT_DEVICE_NO_ACCOUNT_DESCRIPTION";
+ private static final byte[] IMAGE = new byte[]{7, 9};
+ private static final String IMAGE_URL = "IMAGE_URL";
+ private static final String INITIAL_NOTIFICATION_DESCRIPTION =
+ "INITIAL_NOTIFICATION_DESCRIPTION";
+ private static final String INITIAL_NOTIFICATION_DESCRIPTION_NO_ACCOUNT =
+ "INITIAL_NOTIFICATION_DESCRIPTION_NO_ACCOUNT";
+ private static final String INITIAL_PAIRING_DESCRIPTION = "INITIAL_PAIRING_DESCRIPTION";
+ private static final String INTENT_URI = "INTENT_URI";
+ private static final String LOCALE = "LOCALE";
+ private static final String OPEN_COMPANION_APP_DESCRIPTION = "OPEN_COMPANION_APP_DESCRIPTION";
+ private static final String RETRO_ACTIVE_PAIRING_DESCRIPTION =
+ "RETRO_ACTIVE_PAIRING_DESCRIPTION";
+ private static final String SUBSEQUENT_PAIRING_DESCRIPTION = "SUBSEQUENT_PAIRING_DESCRIPTION";
+ private static final String SYNC_CONTACT_DESCRPTION = "SYNC_CONTACT_DESCRPTION";
+ private static final String SYNC_CONTACTS_TITLE = "SYNC_CONTACTS_TITLE";
+ private static final String SYNC_SMS_DESCRIPTION = "SYNC_SMS_DESCRIPTION";
+ private static final String SYNC_SMS_TITLE = "SYNC_SMS_TITLE";
+ private static final float TRIGGER_DISTANCE = 111;
+ private static final String TRUE_WIRELESS_IMAGE_URL_CASE = "TRUE_WIRELESS_IMAGE_URL_CASE";
+ private static final String TRUE_WIRELESS_IMAGE_URL_LEFT_BUD =
+ "TRUE_WIRELESS_IMAGE_URL_LEFT_BUD";
+ private static final String TRUE_WIRELESS_IMAGE_URL_RIGHT_BUD =
+ "TRUE_WIRELESS_IMAGE_URL_RIGHT_BUD";
+ private static final String UNABLE_TO_CONNECT_DESCRIPTION = "UNABLE_TO_CONNECT_DESCRIPTION";
+ private static final String UNABLE_TO_CONNECT_TITLE = "UNABLE_TO_CONNECT_TITLE";
+ private static final String UPDATE_COMPANION_APP_DESCRIPTION =
+ "UPDATE_COMPANION_APP_DESCRIPTION";
+ private static final String WAIT_LAUNCH_COMPANION_APP_DESCRIPTION =
+ "WAIT_LAUNCH_COMPANION_APP_DESCRIPTION";
+ private static final byte[] ACCOUNT_KEY = new byte[]{3};
+ private static final byte[] SHA256_ACCOUNT_KEY_PUBLIC_ADDRESS = new byte[]{2, 8};
+ private static final byte[] ANTI_SPOOFING_KEY = new byte[]{4, 5, 6};
+ private static final String ACTION_URL = "ACTION_URL";
+ private static final int ACTION_URL_TYPE = 1;
+ private static final String APP_NAME = "APP_NAME";
+ private static final int ATTACHMENT_TYPE = 1;
+ private static final byte[] AUTHENTICATION_PUBLIC_KEY_SEC_P256R1 = new byte[]{5, 7};
+ private static final byte[] BLE_RECORD_BYTES = new byte[]{2, 4};
+ private static final int DEBUG_CATEGORY = 1;
+ private static final String DEBUG_MESSAGE = "DEBUG_MESSAGE";
+ private static final String DESCRIPTION = "DESCRIPTION";
+ private static final String DEVICE_NAME = "DEVICE_NAME";
+ private static final String DISPLAY_URL = "DISPLAY_URL";
+ private static final String ENTITY_ID = "ENTITY_ID";
+ private static final String FEATURE_GRAPHIC_URL = "FEATURE_GRAPHIC_URL";
+ private static final long FIRST_OBSERVATION_TIMESTAMP_MILLIS = 8393L;
+ private static final String GROUP_ID = "GROUP_ID";
+ private static final String ICON_FIFE_URL = "ICON_FIFE_URL";
+ private static final byte[] ICON_PNG = new byte[]{2, 5};
+ private static final String ID = "ID";
+ private static final long LAST_OBSERVATION_TIMESTAMP_MILLIS = 934234L;
+ private static final int LAST_USER_EXPERIENCE = 1;
+ private static final long LOST_MILLIS = 393284L;
+ private static final String MAC_ADDRESS = "MAC_ADDRESS";
+ private static final String NAME = "NAME";
+ private static final String PACKAGE_NAME = "PACKAGE_NAME";
+ private static final long PENDING_APP_INSTALL_TIMESTAMP_MILLIS = 832393L;
+ private static final int RSSI = 9;
+ private static final int STATE = 1;
+ private static final String TITLE = "TITLE";
+ private static final String TRIGGER_ID = "TRIGGER_ID";
+ private static final int TX_POWER = 63;
+ private static final int TYPE = 1;
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testHappyPathConvertToFastPairDevicesWithAccountKey() {
+ FastPairAccountKeyDeviceMetadataParcel[] array = {
+ genHappyPathFastPairAccountkeyDeviceMetadataParcel()};
+
+ List<Data.FastPairDeviceWithAccountKey> deviceWithAccountKey =
+ Utils.convertToFastPairDevicesWithAccountKey(array);
+ assertThat(deviceWithAccountKey.size()).isEqualTo(1);
+ assertThat(deviceWithAccountKey.get(0)).isEqualTo(
+ genHappyPathFastPairDeviceWithAccountKey());
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testConvertToFastPairDevicesWithAccountKeyWithNullArray() {
+ FastPairAccountKeyDeviceMetadataParcel[] array = null;
+ assertThat(Utils.convertToFastPairDevicesWithAccountKey(array).size()).isEqualTo(0);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testConvertToFastPairDevicesWithAccountKeyWithNullElement() {
+ FastPairAccountKeyDeviceMetadataParcel[] array = {null};
+ assertThat(Utils.convertToFastPairDevicesWithAccountKey(array).size()).isEqualTo(0);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testConvertToFastPairDevicesWithAccountKeyWithEmptyElementNoCrash() {
+ FastPairAccountKeyDeviceMetadataParcel[] array = {
+ genEmptyFastPairAccountkeyDeviceMetadataParcel()};
+
+ List<Data.FastPairDeviceWithAccountKey> deviceWithAccountKey =
+ Utils.convertToFastPairDevicesWithAccountKey(array);
+ assertThat(deviceWithAccountKey.size()).isEqualTo(1);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testConvertToFastPairDevicesWithAccountKeyWithEmptyMetadataDiscoveryNoCrash() {
+ FastPairAccountKeyDeviceMetadataParcel[] array = {
+ genFastPairAccountkeyDeviceMetadataParcelWithEmptyMetadataDiscoveryItem()};
+
+ List<Data.FastPairDeviceWithAccountKey> deviceWithAccountKey =
+ Utils.convertToFastPairDevicesWithAccountKey(array);
+ assertThat(deviceWithAccountKey.size()).isEqualTo(1);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testConvertToFastPairDevicesWithAccountKeyWithMixedArrayElements() {
+ FastPairAccountKeyDeviceMetadataParcel[] array = {
+ null,
+ genHappyPathFastPairAccountkeyDeviceMetadataParcel(),
+ genEmptyFastPairAccountkeyDeviceMetadataParcel(),
+ genFastPairAccountkeyDeviceMetadataParcelWithEmptyMetadataDiscoveryItem()};
+
+ assertThat(Utils.convertToFastPairDevicesWithAccountKey(array).size()).isEqualTo(3);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testHappyPathConvertToAccountList() {
+ FastPairEligibleAccountParcel[] array = {genHappyPathFastPairEligibleAccountParcel()};
+
+ List<Account> accountList = Utils.convertToAccountList(array);
+ assertThat(accountList.size()).isEqualTo(1);
+ assertThat(accountList.get(0)).isEqualTo(ELIGIBLE_ACCOUNT_1);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testConvertToAccountListNullArray() {
+ FastPairEligibleAccountParcel[] array = null;
+
+ List<Account> accountList = Utils.convertToAccountList(array);
+ assertThat(accountList.size()).isEqualTo(0);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testConvertToAccountListWithNullElement() {
+ FastPairEligibleAccountParcel[] array = {null};
+
+ List<Account> accountList = Utils.convertToAccountList(array);
+ assertThat(accountList.size()).isEqualTo(0);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testConvertToAccountListWithEmptyElementNotCrash() {
+ FastPairEligibleAccountParcel[] array =
+ {genEmptyFastPairEligibleAccountParcel()};
+
+ List<Account> accountList = Utils.convertToAccountList(array);
+ assertThat(accountList.size()).isEqualTo(0);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testConvertToAccountListWithMixedArrayElements() {
+ FastPairEligibleAccountParcel[] array = {
+ genHappyPathFastPairEligibleAccountParcel(),
+ genEmptyFastPairEligibleAccountParcel(),
+ null,
+ genHappyPathFastPairEligibleAccountParcel()};
+
+ List<Account> accountList = Utils.convertToAccountList(array);
+ assertThat(accountList.size()).isEqualTo(2);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testHappyPathConvertToGetObservedDeviceResponse() {
+ Rpcs.GetObservedDeviceResponse response =
+ Utils.convertToGetObservedDeviceResponse(
+ genHappyPathFastPairAntispoofkeyDeviceMetadataParcel());
+ assertThat(response).isEqualTo(genHappyPathObservedDeviceResponse());
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testConvertToGetObservedDeviceResponseWithNullInput() {
+ assertThat(Utils.convertToGetObservedDeviceResponse(null))
+ .isEqualTo(null);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testConvertToGetObservedDeviceResponseWithEmptyInputNotCrash() {
+ Utils.convertToGetObservedDeviceResponse(
+ genEmptyFastPairAntispoofkeyDeviceMetadataParcel());
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testConvertToGetObservedDeviceResponseWithEmptyDeviceMetadataNotCrash() {
+ Utils.convertToGetObservedDeviceResponse(
+ genFastPairAntispoofkeyDeviceMetadataParcelWithEmptyDeviceMetadata());
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testHappyPathConvertToFastPairAccountKeyDeviceMetadata() {
+ FastPairAccountKeyDeviceMetadataParcel metadataParcel =
+ Utils.convertToFastPairAccountKeyDeviceMetadata(genHappyPathFastPairUploadInfo());
+ ensureHappyPathAsExpected(metadataParcel);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testConvertToFastPairAccountKeyDeviceMetadataWithNullInput() {
+ assertThat(Utils.convertToFastPairAccountKeyDeviceMetadata(null)).isEqualTo(null);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void testConvertToFastPairAccountKeyDeviceMetadataWithEmptyFieldsNotCrash() {
+ Utils.convertToFastPairAccountKeyDeviceMetadata(
+ new FastPairUploadInfo(
+ null /* discoveryItem */,
+ null /* accountKey */,
+ null /* sha256AccountKeyPublicAddress */));
+ }
+
+ private static FastPairUploadInfo genHappyPathFastPairUploadInfo() {
+ return new FastPairUploadInfo(
+ genHappyPathStoredDiscoveryItem(),
+ ByteString.copyFrom(ACCOUNT_KEY),
+ ByteString.copyFrom(SHA256_ACCOUNT_KEY_PUBLIC_ADDRESS));
+
+ }
+
+ private static void ensureHappyPathAsExpected(
+ FastPairAccountKeyDeviceMetadataParcel metadataParcel) {
+ assertThat(metadataParcel).isNotNull();
+ assertThat(metadataParcel.accountKey).isEqualTo(ACCOUNT_KEY);
+ assertThat(metadataParcel.sha256AccountKeyPublicAddress)
+ .isEqualTo(SHA256_ACCOUNT_KEY_PUBLIC_ADDRESS);
+ ensureHappyPathAsExpected(metadataParcel.metadata);
+ ensureHappyPathAsExpected(metadataParcel.discoveryItem);
+ }
+
+ private static void ensureHappyPathAsExpected(FastPairDeviceMetadataParcel metadataParcel) {
+ assertThat(metadataParcel).isNotNull();
+
+ assertThat(metadataParcel.assistantSetupHalfSheet).isEqualTo(ASSISTANT_SETUP_HALFSHEET);
+ assertThat(metadataParcel.assistantSetupNotification).isEqualTo(
+ ASSISTANT_SETUP_NOTIFICATION);
+
+
+ assertThat(metadataParcel.confirmPinDescription).isEqualTo(CONFIRM_PIN_DESCRIPTION);
+ assertThat(metadataParcel.confirmPinTitle).isEqualTo(CONFIRM_PIN_TITLE);
+ assertThat(metadataParcel.connectSuccessCompanionAppInstalled).isEqualTo(
+ CONNECT_SUCCESS_COMPANION_APP_INSTALLED);
+ assertThat(metadataParcel.connectSuccessCompanionAppNotInstalled).isEqualTo(
+ CONNECT_SUCCESS_COMPANION_APP_NOT_INSTALLED);
+
+ assertThat(metadataParcel.deviceType).isEqualTo(DEVICE_TYPE);
+
+ assertThat(metadataParcel.failConnectGoToSettingsDescription).isEqualTo(
+ FAIL_CONNECT_GOTO_SETTINGS_DESCRIPTION);
+ assertThat(metadataParcel.fastPairTvConnectDeviceNoAccountDescription).isEqualTo(
+ FAST_PAIR_TV_CONNECT_DEVICE_NO_ACCOUNT_DESCRIPTION);
+
+ assertThat(metadataParcel.initialNotificationDescription).isEqualTo(
+ INITIAL_NOTIFICATION_DESCRIPTION);
+ assertThat(metadataParcel.initialNotificationDescriptionNoAccount).isEqualTo(
+ INITIAL_NOTIFICATION_DESCRIPTION_NO_ACCOUNT);
+ assertThat(metadataParcel.initialPairingDescription).isEqualTo(INITIAL_PAIRING_DESCRIPTION);
+
+
+ assertThat(metadataParcel.retroactivePairingDescription).isEqualTo(
+ RETRO_ACTIVE_PAIRING_DESCRIPTION);
+
+ assertThat(metadataParcel.subsequentPairingDescription).isEqualTo(
+ SUBSEQUENT_PAIRING_DESCRIPTION);
+ assertThat(metadataParcel.syncContactsDescription).isEqualTo(SYNC_CONTACT_DESCRPTION);
+ assertThat(metadataParcel.syncContactsTitle).isEqualTo(SYNC_CONTACTS_TITLE);
+ assertThat(metadataParcel.syncSmsDescription).isEqualTo(SYNC_SMS_DESCRIPTION);
+ assertThat(metadataParcel.syncSmsTitle).isEqualTo(SYNC_SMS_TITLE);
+
+ assertThat(metadataParcel.trueWirelessImageUrlCase).isEqualTo(TRUE_WIRELESS_IMAGE_URL_CASE);
+ assertThat(metadataParcel.trueWirelessImageUrlLeftBud).isEqualTo(
+ TRUE_WIRELESS_IMAGE_URL_LEFT_BUD);
+ assertThat(metadataParcel.trueWirelessImageUrlRightBud).isEqualTo(
+ TRUE_WIRELESS_IMAGE_URL_RIGHT_BUD);
+ assertThat(metadataParcel.waitLaunchCompanionAppDescription).isEqualTo(
+ WAIT_LAUNCH_COMPANION_APP_DESCRIPTION);
+
+ /* do we need upload this? */
+ // assertThat(metadataParcel.locale).isEqualTo(LOCALE);
+ // assertThat(metadataParcel.name).isEqualTo(NAME);
+ // assertThat(metadataParcel.downloadCompanionAppDescription).isEqualTo(
+ // DOWNLOAD_COMPANION_APP_DESCRIPTION);
+ // assertThat(metadataParcel.openCompanionAppDescription).isEqualTo(
+ // OPEN_COMPANION_APP_DESCRIPTION);
+ // assertThat(metadataParcel.triggerDistance).isWithin(DELTA).of(TRIGGER_DISTANCE);
+ // assertThat(metadataParcel.unableToConnectDescription).isEqualTo(
+ // UNABLE_TO_CONNECT_DESCRIPTION);
+ // assertThat(metadataParcel.unableToConnectTitle).isEqualTo(UNABLE_TO_CONNECT_TITLE);
+ // assertThat(metadataParcel.updateCompanionAppDescription).isEqualTo(
+ // UPDATE_COMPANION_APP_DESCRIPTION);
+
+ // assertThat(metadataParcel.bleTxPower).isEqualTo(BLE_TX_POWER);
+ // assertThat(metadataParcel.image).isEqualTo(IMAGE);
+ // assertThat(metadataParcel.imageUrl).isEqualTo(IMAGE_URL);
+ // assertThat(metadataParcel.intentUri).isEqualTo(INTENT_URI);
+ }
+
+ private static void ensureHappyPathAsExpected(FastPairDiscoveryItemParcel itemParcel) {
+ assertThat(itemParcel.actionUrl).isEqualTo(ACTION_URL);
+ assertThat(itemParcel.actionUrlType).isEqualTo(ACTION_URL_TYPE);
+ assertThat(itemParcel.appName).isEqualTo(APP_NAME);
+ assertThat(itemParcel.attachmentType).isEqualTo(ATTACHMENT_TYPE);
+ assertThat(itemParcel.authenticationPublicKeySecp256r1)
+ .isEqualTo(AUTHENTICATION_PUBLIC_KEY_SEC_P256R1);
+ assertThat(itemParcel.bleRecordBytes).isEqualTo(BLE_RECORD_BYTES);
+ assertThat(itemParcel.debugCategory).isEqualTo(DEBUG_CATEGORY);
+ assertThat(itemParcel.debugMessage).isEqualTo(DEBUG_MESSAGE);
+ assertThat(itemParcel.description).isEqualTo(DESCRIPTION);
+ assertThat(itemParcel.deviceName).isEqualTo(DEVICE_NAME);
+ assertThat(itemParcel.displayUrl).isEqualTo(DISPLAY_URL);
+ assertThat(itemParcel.entityId).isEqualTo(ENTITY_ID);
+ assertThat(itemParcel.featureGraphicUrl).isEqualTo(FEATURE_GRAPHIC_URL);
+ assertThat(itemParcel.firstObservationTimestampMillis)
+ .isEqualTo(FIRST_OBSERVATION_TIMESTAMP_MILLIS);
+ assertThat(itemParcel.groupId).isEqualTo(GROUP_ID);
+ assertThat(itemParcel.iconFifeUrl).isEqualTo(ICON_FIFE_URL);
+ assertThat(itemParcel.iconPng).isEqualTo(ICON_PNG);
+ assertThat(itemParcel.id).isEqualTo(ID);
+ assertThat(itemParcel.lastObservationTimestampMillis)
+ .isEqualTo(LAST_OBSERVATION_TIMESTAMP_MILLIS);
+ assertThat(itemParcel.lastUserExperience).isEqualTo(LAST_USER_EXPERIENCE);
+ assertThat(itemParcel.lostMillis).isEqualTo(LOST_MILLIS);
+ assertThat(itemParcel.macAddress).isEqualTo(MAC_ADDRESS);
+ assertThat(itemParcel.packageName).isEqualTo(PACKAGE_NAME);
+ assertThat(itemParcel.pendingAppInstallTimestampMillis)
+ .isEqualTo(PENDING_APP_INSTALL_TIMESTAMP_MILLIS);
+ assertThat(itemParcel.rssi).isEqualTo(RSSI);
+ assertThat(itemParcel.state).isEqualTo(STATE);
+ assertThat(itemParcel.title).isEqualTo(TITLE);
+ assertThat(itemParcel.triggerId).isEqualTo(TRIGGER_ID);
+ assertThat(itemParcel.txPower).isEqualTo(TX_POWER);
+ assertThat(itemParcel.type).isEqualTo(TYPE);
+ }
+
+ private static FastPairEligibleAccountParcel genHappyPathFastPairEligibleAccountParcel() {
+ FastPairEligibleAccountParcel parcel = new FastPairEligibleAccountParcel();
+ parcel.account = ELIGIBLE_ACCOUNT_1;
+ parcel.optIn = true;
+
+ return parcel;
+ }
+
+ private static FastPairEligibleAccountParcel genEmptyFastPairEligibleAccountParcel() {
+ return new FastPairEligibleAccountParcel();
+ }
+
+ private static FastPairDeviceMetadataParcel genEmptyFastPairDeviceMetadataParcel() {
+ return new FastPairDeviceMetadataParcel();
+ }
+
+ private static FastPairDiscoveryItemParcel genEmptyFastPairDiscoveryItemParcel() {
+ return new FastPairDiscoveryItemParcel();
+ }
+
+ private static FastPairAccountKeyDeviceMetadataParcel
+ genEmptyFastPairAccountkeyDeviceMetadataParcel() {
+ return new FastPairAccountKeyDeviceMetadataParcel();
+ }
+
+ private static FastPairAccountKeyDeviceMetadataParcel
+ genFastPairAccountkeyDeviceMetadataParcelWithEmptyMetadataDiscoveryItem() {
+ FastPairAccountKeyDeviceMetadataParcel parcel =
+ new FastPairAccountKeyDeviceMetadataParcel();
+ parcel.metadata = genEmptyFastPairDeviceMetadataParcel();
+ parcel.discoveryItem = genEmptyFastPairDiscoveryItemParcel();
+
+ return parcel;
+ }
+
+ private static FastPairAccountKeyDeviceMetadataParcel
+ genHappyPathFastPairAccountkeyDeviceMetadataParcel() {
+ FastPairAccountKeyDeviceMetadataParcel parcel =
+ new FastPairAccountKeyDeviceMetadataParcel();
+ parcel.accountKey = ACCOUNT_KEY;
+ parcel.metadata = genHappyPathFastPairDeviceMetadataParcel();
+ parcel.sha256AccountKeyPublicAddress = SHA256_ACCOUNT_KEY_PUBLIC_ADDRESS;
+ parcel.discoveryItem = genHappyPathFastPairDiscoveryItemParcel();
+
+ return parcel;
+ }
+
+ private static FastPairDeviceMetadataParcel genHappyPathFastPairDeviceMetadataParcel() {
+ FastPairDeviceMetadataParcel parcel = new FastPairDeviceMetadataParcel();
+
+ parcel.assistantSetupHalfSheet = ASSISTANT_SETUP_HALFSHEET;
+ parcel.assistantSetupNotification = ASSISTANT_SETUP_NOTIFICATION;
+ parcel.bleTxPower = BLE_TX_POWER;
+ parcel.confirmPinDescription = CONFIRM_PIN_DESCRIPTION;
+ parcel.confirmPinTitle = CONFIRM_PIN_TITLE;
+ parcel.connectSuccessCompanionAppInstalled = CONNECT_SUCCESS_COMPANION_APP_INSTALLED;
+ parcel.connectSuccessCompanionAppNotInstalled =
+ CONNECT_SUCCESS_COMPANION_APP_NOT_INSTALLED;
+ parcel.deviceType = DEVICE_TYPE;
+ parcel.downloadCompanionAppDescription = DOWNLOAD_COMPANION_APP_DESCRIPTION;
+ parcel.failConnectGoToSettingsDescription = FAIL_CONNECT_GOTO_SETTINGS_DESCRIPTION;
+ parcel.fastPairTvConnectDeviceNoAccountDescription =
+ FAST_PAIR_TV_CONNECT_DEVICE_NO_ACCOUNT_DESCRIPTION;
+ parcel.image = IMAGE;
+ parcel.imageUrl = IMAGE_URL;
+ parcel.initialNotificationDescription = INITIAL_NOTIFICATION_DESCRIPTION;
+ parcel.initialNotificationDescriptionNoAccount =
+ INITIAL_NOTIFICATION_DESCRIPTION_NO_ACCOUNT;
+ parcel.initialPairingDescription = INITIAL_PAIRING_DESCRIPTION;
+ parcel.intentUri = INTENT_URI;
+ parcel.locale = LOCALE;
+ parcel.name = NAME;
+ parcel.openCompanionAppDescription = OPEN_COMPANION_APP_DESCRIPTION;
+ parcel.retroactivePairingDescription = RETRO_ACTIVE_PAIRING_DESCRIPTION;
+ parcel.subsequentPairingDescription = SUBSEQUENT_PAIRING_DESCRIPTION;
+ parcel.syncContactsDescription = SYNC_CONTACT_DESCRPTION;
+ parcel.syncContactsTitle = SYNC_CONTACTS_TITLE;
+ parcel.syncSmsDescription = SYNC_SMS_DESCRIPTION;
+ parcel.syncSmsTitle = SYNC_SMS_TITLE;
+ parcel.triggerDistance = TRIGGER_DISTANCE;
+ parcel.trueWirelessImageUrlCase = TRUE_WIRELESS_IMAGE_URL_CASE;
+ parcel.trueWirelessImageUrlLeftBud = TRUE_WIRELESS_IMAGE_URL_LEFT_BUD;
+ parcel.trueWirelessImageUrlRightBud = TRUE_WIRELESS_IMAGE_URL_RIGHT_BUD;
+ parcel.unableToConnectDescription = UNABLE_TO_CONNECT_DESCRIPTION;
+ parcel.unableToConnectTitle = UNABLE_TO_CONNECT_TITLE;
+ parcel.updateCompanionAppDescription = UPDATE_COMPANION_APP_DESCRIPTION;
+ parcel.waitLaunchCompanionAppDescription = WAIT_LAUNCH_COMPANION_APP_DESCRIPTION;
+
+ return parcel;
+ }
+
+ private static Cache.StoredDiscoveryItem genHappyPathStoredDiscoveryItem() {
+ Cache.StoredDiscoveryItem.Builder storedDiscoveryItemBuilder =
+ Cache.StoredDiscoveryItem.newBuilder();
+ storedDiscoveryItemBuilder.setActionUrl(ACTION_URL);
+ storedDiscoveryItemBuilder.setActionUrlType(Cache.ResolvedUrlType.WEBPAGE);
+ storedDiscoveryItemBuilder.setAppName(APP_NAME);
+ storedDiscoveryItemBuilder.setAttachmentType(
+ Cache.DiscoveryAttachmentType.DISCOVERY_ATTACHMENT_TYPE_NORMAL);
+ storedDiscoveryItemBuilder.setAuthenticationPublicKeySecp256R1(
+ ByteString.copyFrom(AUTHENTICATION_PUBLIC_KEY_SEC_P256R1));
+ storedDiscoveryItemBuilder.setBleRecordBytes(ByteString.copyFrom(BLE_RECORD_BYTES));
+ storedDiscoveryItemBuilder.setDebugCategory(
+ Cache.StoredDiscoveryItem.DebugMessageCategory.STATUS_VALID_NOTIFICATION);
+ storedDiscoveryItemBuilder.setDebugMessage(DEBUG_MESSAGE);
+ storedDiscoveryItemBuilder.setDescription(DESCRIPTION);
+ storedDiscoveryItemBuilder.setDeviceName(DEVICE_NAME);
+ storedDiscoveryItemBuilder.setDisplayUrl(DISPLAY_URL);
+ storedDiscoveryItemBuilder.setEntityId(ENTITY_ID);
+ storedDiscoveryItemBuilder.setFeatureGraphicUrl(FEATURE_GRAPHIC_URL);
+ storedDiscoveryItemBuilder.setFirstObservationTimestampMillis(
+ FIRST_OBSERVATION_TIMESTAMP_MILLIS);
+ storedDiscoveryItemBuilder.setGroupId(GROUP_ID);
+ storedDiscoveryItemBuilder.setIconFifeUrl(ICON_FIFE_URL);
+ storedDiscoveryItemBuilder.setIconPng(ByteString.copyFrom(ICON_PNG));
+ storedDiscoveryItemBuilder.setId(ID);
+ storedDiscoveryItemBuilder.setLastObservationTimestampMillis(
+ LAST_OBSERVATION_TIMESTAMP_MILLIS);
+ storedDiscoveryItemBuilder.setLastUserExperience(
+ Cache.StoredDiscoveryItem.ExperienceType.EXPERIENCE_GOOD);
+ storedDiscoveryItemBuilder.setLostMillis(LOST_MILLIS);
+ storedDiscoveryItemBuilder.setMacAddress(MAC_ADDRESS);
+ storedDiscoveryItemBuilder.setPackageName(PACKAGE_NAME);
+ storedDiscoveryItemBuilder.setPendingAppInstallTimestampMillis(
+ PENDING_APP_INSTALL_TIMESTAMP_MILLIS);
+ storedDiscoveryItemBuilder.setRssi(RSSI);
+ storedDiscoveryItemBuilder.setState(Cache.StoredDiscoveryItem.State.STATE_ENABLED);
+ storedDiscoveryItemBuilder.setTitle(TITLE);
+ storedDiscoveryItemBuilder.setTriggerId(TRIGGER_ID);
+ storedDiscoveryItemBuilder.setTxPower(TX_POWER);
+ storedDiscoveryItemBuilder.setType(Cache.NearbyType.NEARBY_PROXIMITY_BEACON);
+
+ FastPairStrings.Builder stringsBuilder = FastPairStrings.newBuilder();
+ stringsBuilder.setAssistantHalfSheetDescription(ASSISTANT_SETUP_HALFSHEET);
+ stringsBuilder.setAssistantNotificationDescription(ASSISTANT_SETUP_NOTIFICATION);
+ stringsBuilder.setConfirmPinDescription(CONFIRM_PIN_DESCRIPTION);
+ stringsBuilder.setConfirmPinTitle(CONFIRM_PIN_TITLE);
+ stringsBuilder.setPairingFinishedCompanionAppInstalled(
+ CONNECT_SUCCESS_COMPANION_APP_INSTALLED);
+ stringsBuilder.setPairingFinishedCompanionAppNotInstalled(
+ CONNECT_SUCCESS_COMPANION_APP_NOT_INSTALLED);
+ stringsBuilder.setPairingFailDescription(
+ FAIL_CONNECT_GOTO_SETTINGS_DESCRIPTION);
+ stringsBuilder.setFastPairTvConnectDeviceNoAccountDescription(
+ FAST_PAIR_TV_CONNECT_DEVICE_NO_ACCOUNT_DESCRIPTION);
+ stringsBuilder.setTapToPairWithAccount(
+ INITIAL_NOTIFICATION_DESCRIPTION);
+ stringsBuilder.setTapToPairWithoutAccount(
+ INITIAL_NOTIFICATION_DESCRIPTION_NO_ACCOUNT);
+ stringsBuilder.setInitialPairingDescription(INITIAL_PAIRING_DESCRIPTION);
+ stringsBuilder.setRetroactivePairingDescription(RETRO_ACTIVE_PAIRING_DESCRIPTION);
+ stringsBuilder.setSubsequentPairingDescription(SUBSEQUENT_PAIRING_DESCRIPTION);
+ stringsBuilder.setSyncContactsDescription(SYNC_CONTACT_DESCRPTION);
+ stringsBuilder.setSyncContactsTitle(SYNC_CONTACTS_TITLE);
+ stringsBuilder.setSyncSmsDescription(SYNC_SMS_DESCRIPTION);
+ stringsBuilder.setSyncSmsTitle(SYNC_SMS_TITLE);
+ stringsBuilder.setWaitAppLaunchDescription(WAIT_LAUNCH_COMPANION_APP_DESCRIPTION);
+ storedDiscoveryItemBuilder.setFastPairStrings(stringsBuilder.build());
+
+ Cache.FastPairInformation.Builder fpInformationBuilder =
+ Cache.FastPairInformation.newBuilder();
+ Rpcs.TrueWirelessHeadsetImages.Builder imagesBuilder =
+ Rpcs.TrueWirelessHeadsetImages.newBuilder();
+ imagesBuilder.setCaseUrl(TRUE_WIRELESS_IMAGE_URL_CASE);
+ imagesBuilder.setLeftBudUrl(TRUE_WIRELESS_IMAGE_URL_LEFT_BUD);
+ imagesBuilder.setRightBudUrl(TRUE_WIRELESS_IMAGE_URL_RIGHT_BUD);
+ fpInformationBuilder.setTrueWirelessImages(imagesBuilder.build());
+ fpInformationBuilder.setDeviceType(Rpcs.DeviceType.HEADPHONES);
+
+ storedDiscoveryItemBuilder.setFastPairInformation(fpInformationBuilder.build());
+ storedDiscoveryItemBuilder.setTxPower(TX_POWER);
+
+ storedDiscoveryItemBuilder.setIconPng(ByteString.copyFrom(ICON_PNG));
+ storedDiscoveryItemBuilder.setIconFifeUrl(ICON_FIFE_URL);
+ storedDiscoveryItemBuilder.setActionUrl(ACTION_URL);
+
+ return storedDiscoveryItemBuilder.build();
+ }
+
+ private static Data.FastPairDeviceWithAccountKey genHappyPathFastPairDeviceWithAccountKey() {
+ Data.FastPairDeviceWithAccountKey.Builder fpDeviceBuilder =
+ Data.FastPairDeviceWithAccountKey.newBuilder();
+ fpDeviceBuilder.setAccountKey(ByteString.copyFrom(ACCOUNT_KEY));
+ fpDeviceBuilder.setSha256AccountKeyPublicAddress(
+ ByteString.copyFrom(SHA256_ACCOUNT_KEY_PUBLIC_ADDRESS));
+ fpDeviceBuilder.setDiscoveryItem(genHappyPathStoredDiscoveryItem());
+
+ return fpDeviceBuilder.build();
+ }
+
+ private static FastPairDiscoveryItemParcel genHappyPathFastPairDiscoveryItemParcel() {
+ FastPairDiscoveryItemParcel parcel = new FastPairDiscoveryItemParcel();
+ parcel.actionUrl = ACTION_URL;
+ parcel.actionUrlType = ACTION_URL_TYPE;
+ parcel.appName = APP_NAME;
+ parcel.attachmentType = ATTACHMENT_TYPE;
+ parcel.authenticationPublicKeySecp256r1 = AUTHENTICATION_PUBLIC_KEY_SEC_P256R1;
+ parcel.bleRecordBytes = BLE_RECORD_BYTES;
+ parcel.debugCategory = DEBUG_CATEGORY;
+ parcel.debugMessage = DEBUG_MESSAGE;
+ parcel.description = DESCRIPTION;
+ parcel.deviceName = DEVICE_NAME;
+ parcel.displayUrl = DISPLAY_URL;
+ parcel.entityId = ENTITY_ID;
+ parcel.featureGraphicUrl = FEATURE_GRAPHIC_URL;
+ parcel.firstObservationTimestampMillis = FIRST_OBSERVATION_TIMESTAMP_MILLIS;
+ parcel.groupId = GROUP_ID;
+ parcel.iconFifeUrl = ICON_FIFE_URL;
+ parcel.iconPng = ICON_PNG;
+ parcel.id = ID;
+ parcel.lastObservationTimestampMillis = LAST_OBSERVATION_TIMESTAMP_MILLIS;
+ parcel.lastUserExperience = LAST_USER_EXPERIENCE;
+ parcel.lostMillis = LOST_MILLIS;
+ parcel.macAddress = MAC_ADDRESS;
+ parcel.packageName = PACKAGE_NAME;
+ parcel.pendingAppInstallTimestampMillis = PENDING_APP_INSTALL_TIMESTAMP_MILLIS;
+ parcel.rssi = RSSI;
+ parcel.state = STATE;
+ parcel.title = TITLE;
+ parcel.triggerId = TRIGGER_ID;
+ parcel.txPower = TX_POWER;
+ parcel.type = TYPE;
+
+ return parcel;
+ }
+
+ private static Rpcs.GetObservedDeviceResponse genHappyPathObservedDeviceResponse() {
+ Rpcs.Device.Builder deviceBuilder = Rpcs.Device.newBuilder();
+ deviceBuilder.setAntiSpoofingKeyPair(Rpcs.AntiSpoofingKeyPair.newBuilder()
+ .setPublicKey(ByteString.copyFrom(ANTI_SPOOFING_KEY))
+ .build());
+ Rpcs.TrueWirelessHeadsetImages.Builder imagesBuilder =
+ Rpcs.TrueWirelessHeadsetImages.newBuilder();
+ imagesBuilder.setLeftBudUrl(TRUE_WIRELESS_IMAGE_URL_LEFT_BUD);
+ imagesBuilder.setRightBudUrl(TRUE_WIRELESS_IMAGE_URL_RIGHT_BUD);
+ imagesBuilder.setCaseUrl(TRUE_WIRELESS_IMAGE_URL_CASE);
+ deviceBuilder.setTrueWirelessImages(imagesBuilder.build());
+ deviceBuilder.setImageUrl(IMAGE_URL);
+ deviceBuilder.setIntentUri(INTENT_URI);
+ deviceBuilder.setName(NAME);
+ deviceBuilder.setBleTxPower(BLE_TX_POWER);
+ deviceBuilder.setTriggerDistance(TRIGGER_DISTANCE);
+ deviceBuilder.setDeviceType(Rpcs.DeviceType.HEADPHONES);
+
+ return Rpcs.GetObservedDeviceResponse.newBuilder()
+ .setDevice(deviceBuilder.build())
+ .setImage(ByteString.copyFrom(IMAGE))
+ .setStrings(Rpcs.ObservedDeviceStrings.newBuilder()
+ .setAssistantSetupHalfSheet(ASSISTANT_SETUP_HALFSHEET)
+ .setAssistantSetupNotification(ASSISTANT_SETUP_NOTIFICATION)
+ .setConfirmPinDescription(CONFIRM_PIN_DESCRIPTION)
+ .setConfirmPinTitle(CONFIRM_PIN_TITLE)
+ .setConnectSuccessCompanionAppInstalled(
+ CONNECT_SUCCESS_COMPANION_APP_INSTALLED)
+ .setConnectSuccessCompanionAppNotInstalled(
+ CONNECT_SUCCESS_COMPANION_APP_NOT_INSTALLED)
+ .setDownloadCompanionAppDescription(
+ DOWNLOAD_COMPANION_APP_DESCRIPTION)
+ .setFailConnectGoToSettingsDescription(
+ FAIL_CONNECT_GOTO_SETTINGS_DESCRIPTION)
+ .setFastPairTvConnectDeviceNoAccountDescription(
+ FAST_PAIR_TV_CONNECT_DEVICE_NO_ACCOUNT_DESCRIPTION)
+ .setInitialNotificationDescription(
+ INITIAL_NOTIFICATION_DESCRIPTION)
+ .setInitialNotificationDescriptionNoAccount(
+ INITIAL_NOTIFICATION_DESCRIPTION_NO_ACCOUNT)
+ .setInitialPairingDescription(
+ INITIAL_PAIRING_DESCRIPTION)
+ .setLocale(LOCALE)
+ .setOpenCompanionAppDescription(
+ OPEN_COMPANION_APP_DESCRIPTION)
+ .setRetroactivePairingDescription(
+ RETRO_ACTIVE_PAIRING_DESCRIPTION)
+ .setSubsequentPairingDescription(
+ SUBSEQUENT_PAIRING_DESCRIPTION)
+ .setSyncContactsDescription(
+ SYNC_CONTACT_DESCRPTION)
+ .setSyncContactsTitle(
+ SYNC_CONTACTS_TITLE)
+ .setSyncSmsDescription(
+ SYNC_SMS_DESCRIPTION)
+ .setSyncSmsTitle(
+ SYNC_SMS_TITLE)
+ .setUnableToConnectDescription(
+ UNABLE_TO_CONNECT_DESCRIPTION)
+ .setUnableToConnectTitle(
+ UNABLE_TO_CONNECT_TITLE)
+ .setUpdateCompanionAppDescription(
+ UPDATE_COMPANION_APP_DESCRIPTION)
+ .setWaitLaunchCompanionAppDescription(
+ WAIT_LAUNCH_COMPANION_APP_DESCRIPTION)
+ .build())
+ .build();
+ }
+
+ private static FastPairAntispoofkeyDeviceMetadataParcel
+ genHappyPathFastPairAntispoofkeyDeviceMetadataParcel() {
+ FastPairAntispoofkeyDeviceMetadataParcel parcel =
+ new FastPairAntispoofkeyDeviceMetadataParcel();
+ parcel.antiSpoofPublicKey = ANTI_SPOOFING_KEY;
+ parcel.deviceMetadata = genHappyPathFastPairDeviceMetadataParcel();
+
+ return parcel;
+ }
+
+ private static FastPairAntispoofkeyDeviceMetadataParcel
+ genFastPairAntispoofkeyDeviceMetadataParcelWithEmptyDeviceMetadata() {
+ FastPairAntispoofkeyDeviceMetadataParcel parcel =
+ new FastPairAntispoofkeyDeviceMetadataParcel();
+ parcel.antiSpoofPublicKey = ANTI_SPOOFING_KEY;
+ parcel.deviceMetadata = genEmptyFastPairDeviceMetadataParcel();
+
+ return parcel;
+ }
+
+ private static FastPairAntispoofkeyDeviceMetadataParcel
+ genEmptyFastPairAntispoofkeyDeviceMetadataParcel() {
+ return new FastPairAntispoofkeyDeviceMetadataParcel();
+ }
+}