Merge "Catch the exception otherwise if gms core side does not setup correctly system will crush"
diff --git a/nearby/framework/java/android/nearby/PresenceDevice.java b/nearby/framework/java/android/nearby/PresenceDevice.java
new file mode 100644
index 0000000..61326c6
--- /dev/null
+++ b/nearby/framework/java/android/nearby/PresenceDevice.java
@@ -0,0 +1,307 @@
+/*
+ * 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.Nullable;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Represents a Presence device from nearby scans.
+ *
+ * @hide
+ */
+public final class PresenceDevice extends NearbyDevice implements Parcelable {
+
+ /** The type of presence device. */
+ /** @hide **/
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({
+ DeviceType.UNKNOWN,
+ DeviceType.PHONE,
+ DeviceType.TABLET,
+ DeviceType.DISPLAY,
+ DeviceType.LAPTOP,
+ DeviceType.TV,
+ DeviceType.WATCH,
+ })
+ public @interface DeviceType {
+ /** The type of the device is unknown. */
+ int UNKNOWN = 0;
+ /** The device is a phone. */
+ int PHONE = 1;
+ /** The device is a tablet. */
+ int TABLET = 2;
+ /** The device is a display. */
+ int DISPLAY = 3;
+ /** The device is a laptop. */
+ int LAPTOP = 4;
+ /** The device is a TV. */
+ int TV = 5;
+ /** The device is a watch. */
+ int WATCH = 6;
+ }
+
+ private final String mDeviceId;
+ 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;
+ }
+
+ /**
+ * The id of the device.
+ *
+ * <p>This id is not a hardware id. It may rotate based on the remote device's broadcasts.
+ */
+ @NonNull
+ public String getDeviceId() {
+ return mDeviceId;
+ }
+
+ /** The type of the device. */
+ @DeviceType
+ public int getDeviceType() {
+ return mDeviceType;
+ }
+
+ /** An image URL representing the device. */
+ @Nullable
+ public String getDeviceImageUrl() {
+ return mDeviceImageUrl;
+ }
+
+ /** The timestamp (since boot) when the device is discovered. */
+ public long getDiscoveryTimestampMillis() {
+ return mDiscoveryTimestampMillis;
+ }
+
+ /**
+ * The extended properties of the device.
+ */
+ @NonNull
+ public Bundle getExtendedProperties() {
+ return mExtendedProperties;
+ }
+
+ private PresenceDevice(String deviceName, int mMedium, int rssi, String deviceId,
+ int deviceType,
+ String deviceImageUrl, long discoveryTimestampMillis,
+ Bundle extendedProperties) {
+ // TODO (b/217462253): change medium to a set in NearbyDevice.
+ super(deviceName, mMedium, rssi);
+ mDeviceId = deviceId;
+ mDeviceType = deviceType;
+ mDeviceImageUrl = deviceImageUrl;
+ mDiscoveryTimestampMillis = discoveryTimestampMillis;
+ mExtendedProperties = extendedProperties;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeInt(mName == null ? 0 : 1);
+ if (mName != null) {
+ dest.writeString(mName);
+ }
+ dest.writeInt(mMedium);
+ dest.writeInt(mRssi);
+ dest.writeString(mDeviceId);
+ dest.writeInt(mDeviceType);
+ dest.writeInt(mDeviceImageUrl == null ? 0 : 1);
+ if (mDeviceImageUrl != null) {
+ dest.writeString(mDeviceImageUrl);
+ }
+ dest.writeLong(mDiscoveryTimestampMillis);
+ dest.writeBundle(mExtendedProperties);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @NonNull
+ public static final Creator<PresenceDevice> CREATOR = new Creator<PresenceDevice>() {
+ @Override
+ public PresenceDevice createFromParcel(Parcel in) {
+ Builder builder = new Builder();
+ if (in.readInt() == 1) {
+ builder.setName(in.readString());
+ }
+ builder.setMedium(in.readInt());
+ builder.setRssi(in.readInt());
+ builder.setDeviceId(in.readString());
+ builder.setDeviceType(in.readInt());
+ if (in.readInt() == 1) {
+ builder.setDeviceImageUrl(in.readString());
+ }
+ builder.setDiscoveryTimestampMillis(in.readLong());
+ Bundle bundle = in.readBundle();
+ for (String key : bundle.keySet()) {
+ builder.addExtendedProperty(key, bundle.getCharSequence(key).toString());
+ }
+ return builder.build();
+ }
+
+ @Override
+ public PresenceDevice[] newArray(int size) {
+ return new PresenceDevice[size];
+ }
+ };
+
+ /**
+ * Builder class for {@link PresenceDevice}.
+ *
+ * @hide
+ */
+ public static final class Builder {
+
+ private final Bundle mExtendedProperties;
+
+ private String mName;
+ private int mRssi;
+ private int mMedium;
+ private String mDeviceId;
+ private int mDeviceType;
+ private String mDeviceImageUrl;
+ private long mDiscoveryTimestampMillis;
+
+ public Builder() {
+ mExtendedProperties = new Bundle();
+ mRssi = -100;
+ }
+
+ /**
+ * Sets the name of the Presence device.
+ *
+ * @param name Name of the Presence. Can be {@code null} if there is no name.
+ */
+ @NonNull
+ public Builder setName(@android.annotation.Nullable String name) {
+ mName = name;
+ return this;
+ }
+
+ /**
+ * Sets 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;
+ return this;
+ }
+
+ /**
+ * Sets the RSSI on the discovered Presence device.
+ *
+ * @param rssi The received signal strength in dBm.
+ */
+ @NonNull
+ public Builder setRssi(int rssi) {
+ mRssi = rssi;
+ return this;
+ }
+
+ /**
+ * Sets the identifier on the discovered Presence device.
+ *
+ * @param deviceId Identifier of the Presence device.
+ */
+ @NonNull
+ public Builder setDeviceId(@NonNull String deviceId) {
+ mDeviceId = deviceId;
+ return this;
+ }
+
+
+ /**
+ * Sets the type of discovered Presence device.
+ *
+ * @param deviceType Type of the Presence device.
+ */
+ @NonNull
+ public Builder setDeviceType(int deviceType) {
+ mDeviceType = deviceType;
+ return this;
+ }
+
+
+ /**
+ * Sets the image url of the discovered Presence device.
+ *
+ * @param deviceImageUrl Url of the image for the Presence device.
+ */
+ @NonNull
+ public Builder setDeviceImageUrl(@NonNull String deviceImageUrl) {
+ mDeviceImageUrl = deviceImageUrl;
+ return this;
+ }
+
+
+ /**
+ * Sets discovery timestamp, the clock is based on elapsed time.
+ *
+ * @param discoveryTimestampMillis Timestamp when the presence device is discovered.
+ */
+ @NonNull
+ public Builder setDiscoveryTimestampMillis(long discoveryTimestampMillis) {
+ mDiscoveryTimestampMillis = discoveryTimestampMillis;
+ return this;
+ }
+
+
+ /**
+ * Adds an extended property of the discovered presence device.
+ *
+ * @param key Key of the extended property.
+ * @param value Value of the extended property,
+ */
+ @NonNull
+ public Builder addExtendedProperty(@NonNull String key, @NonNull String value) {
+ mExtendedProperties.putCharSequence(key, value);
+ return this;
+ }
+
+ /**
+ * Builds a Presence device.
+ */
+ @NonNull
+ public PresenceDevice build() {
+ return new PresenceDevice(mName, mMedium, mRssi, mDeviceId, mDeviceType,
+ mDeviceImageUrl,
+ mDiscoveryTimestampMillis, mExtendedProperties);
+ }
+ }
+}
diff --git a/nearby/framework/java/android/nearby/PresenceScanFilter.java b/nearby/framework/java/android/nearby/PresenceScanFilter.java
new file mode 100644
index 0000000..61e5049
--- /dev/null
+++ b/nearby/framework/java/android/nearby/PresenceScanFilter.java
@@ -0,0 +1,235 @@
+/*
+ * 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.Nullable;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.ArraySet;
+
+import com.android.internal.util.Preconditions;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Filter for scanning a nearby presence device.
+ *
+ * @hide
+ */
+public final class PresenceScanFilter extends ScanFilter implements Parcelable {
+
+ private final List<byte[]> mCertificates;
+ private final List<Integer> mPresenceIdentities;
+ private final List<Integer> mPresenceActions;
+ private final Bundle mExtendedProperties;
+
+ /**
+ * A list of certificates to filter on.
+ */
+ @NonNull
+ public List<byte[]> getCertificates() {
+ return mCertificates;
+ }
+
+ /**
+ * A list of presence identities for matching.
+ */
+ @NonNull
+ public List<Integer> getPresenceIdentities() {
+ return mPresenceIdentities;
+ }
+
+ /**
+ * A list of presence actions for matching.
+ */
+ @NonNull
+ public List<Integer> getPresenceActions() {
+ return mPresenceActions;
+ }
+
+ /**
+ * A bundle of extended properties for matching.
+ */
+ @NonNull
+ public Bundle getExtendedProperties() {
+ return mExtendedProperties;
+ }
+
+ private PresenceScanFilter(int rssiThreshold, List<byte[]> certificates,
+ List<Integer> presenceIdentities, List<Integer> presenceActions,
+ Bundle extendedProperties) {
+ super(ScanRequest.SCAN_TYPE_NEARBY_PRESENCE, rssiThreshold);
+ mCertificates = new ArrayList<>(certificates);
+ mPresenceIdentities = new ArrayList<>(presenceIdentities);
+ 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<>();
+ if (in.readInt() != 0) {
+ in.readList(mPresenceIdentities, Integer.class.getClassLoader(), Integer.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));
+ }
+ }
+
+ @NonNull
+ public static final Creator<PresenceScanFilter> CREATOR = new Creator<PresenceScanFilter>() {
+ @Override
+ public PresenceScanFilter createFromParcel(Parcel in) {
+ // Skip Scan Filter type as it's used for parent class.
+ in.readInt();
+ return createFromParcelBody(in);
+ }
+
+ @Override
+ public PresenceScanFilter[] newArray(int size) {
+ return new PresenceScanFilter[size];
+ }
+ };
+
+ /**
+ * Create a {@link PresenceScanFilter} from the parcel body. Scan Filter type is skipped.
+ */
+ static PresenceScanFilter createFromParcelBody(Parcel in) {
+ return new PresenceScanFilter(in);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @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(mPresenceActions.size());
+ if (!mPresenceActions.isEmpty()) {
+ dest.writeList(mPresenceActions);
+ }
+ dest.writeBundle(mExtendedProperties);
+ }
+
+ /**
+ * Builder for {@link PresenceScanFilter}.
+ *
+ * @hide
+ */
+ public static final class Builder {
+ private int mRssiThreshold;
+ private final Set<byte[]> mCertificates;
+ private final Set<Integer> mPresenceIdentities;
+ private final Set<Integer> mPresenceActions;
+ private final Bundle mExtendedProperties;
+
+ public Builder() {
+ mRssiThreshold = -100;
+ mCertificates = new ArraySet<>();
+ mPresenceIdentities = new ArraySet<>();
+ mPresenceActions = new ArraySet<>();
+ mExtendedProperties = new Bundle();
+ }
+
+ /**
+ * Sets the rssi threshold for the scan request.
+ */
+ @NonNull
+ public Builder setRssiThreshold(int rssiThreshold) {
+ mRssiThreshold = rssiThreshold;
+ return this;
+ }
+
+ /**
+ * Adds a list of certificates the scan filter is expected to match.
+ */
+
+ @NonNull
+ public Builder addCertificate(@NonNull byte[] certificate) {
+ mCertificates.add(certificate);
+ return this;
+ }
+
+ /**
+ * Adds a presence identity for filtering.
+ */
+ @NonNull
+ public Builder addPresenceIdentity(int identity) {
+ mPresenceIdentities.add(identity);
+ return this;
+ }
+
+ /**
+ * Adds a presence action for filtering.
+ */
+ @NonNull
+ public Builder addPresenceAction(int action) {
+ mPresenceActions.add(action);
+ return this;
+ }
+
+ /**
+ * Add an extended property for scan filtering.
+ */
+ @NonNull
+ public Builder addExtendedProperty(@NonNull String key, @Nullable String value) {
+ mExtendedProperties.putCharSequence(key, value);
+ return this;
+ }
+
+ /**
+ * Builds the scan filter.
+ */
+ @NonNull
+ public PresenceScanFilter build() {
+ Preconditions.checkState(!mCertificates.isEmpty(), "certificates cannot be empty");
+ return new PresenceScanFilter(mRssiThreshold, new ArrayList<>(mCertificates),
+ new ArrayList<>(mPresenceIdentities),
+ new ArrayList<>(mPresenceActions),
+ mExtendedProperties);
+ }
+ }
+}
diff --git a/nearby/framework/java/android/nearby/ScanFilter.java b/nearby/framework/java/android/nearby/ScanFilter.java
new file mode 100644
index 0000000..0b2a754
--- /dev/null
+++ b/nearby/framework/java/android/nearby/ScanFilter.java
@@ -0,0 +1,101 @@
+/*
+ * 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.SuppressLint;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Filter for scanning a nearby device.
+ *
+ * @hide
+ */
+@SuppressLint("ParcelNotFinal") // ScanFilter constructor is not public
+public abstract class ScanFilter implements Parcelable {
+ public static final @NonNull Creator<ScanFilter> CREATOR = new Creator<ScanFilter>() {
+ @Override
+ public ScanFilter createFromParcel(Parcel in) {
+ int type = in.readInt();
+ switch (type) {
+ case ScanRequest.SCAN_TYPE_NEARBY_PRESENCE:
+ return PresenceScanFilter.createFromParcelBody(in);
+ default:
+ throw new IllegalStateException(
+ "Unexpected scan type (value " + type + ") in parcel.");
+ }
+ }
+
+ @Override
+ public ScanFilter[] newArray(int size) {
+ return new ScanFilter[size];
+ }
+ };
+
+ private final @ScanRequest.ScanType int mType;
+ private final int mRssiThreshold;
+
+ /**
+ * Constructs a Scan Filter.
+ *
+ * @hide
+ */
+ ScanFilter(@ScanRequest.ScanType int type, int rssiThreshold) {
+ mType = type;
+ mRssiThreshold = rssiThreshold;
+ }
+
+ /**
+ * Constructs a Scan Filter.
+ *
+ * @hide
+ */
+ ScanFilter(@ScanRequest.ScanType int type, Parcel in) {
+ mType = type;
+ mRssiThreshold = in.readInt();
+ }
+
+ /**
+ * Returns the type of this scan filter.
+ */
+ public @ScanRequest.ScanType int getType() {
+ return mType;
+ }
+
+ /**
+ * Minimum RSSI of the received scan result.
+ */
+ public int getRssiThreshold() {
+ return mRssiThreshold;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeInt(mType);
+ dest.writeInt(mRssiThreshold);
+ }
+
+ /**
+ * No special parcel contents.
+ */
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+}
diff --git a/nearby/framework/java/android/nearby/ScanRequest.java b/nearby/framework/java/android/nearby/ScanRequest.java
index 737f574..9180d5e 100644
--- a/nearby/framework/java/android/nearby/ScanRequest.java
+++ b/nearby/framework/java/android/nearby/ScanRequest.java
@@ -30,6 +30,8 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
+import java.util.List;
import java.util.Objects;
/**
@@ -48,6 +50,7 @@
public static final int SCAN_TYPE_NEARBY_PRESENCE = 3;
/** Scan type for scanning devices using exposure notification protocol. */
public static final int SCAN_TYPE_EXPOSURE_NOTIFICATION = 4;
+
/** Scan mode uses highest duty cycle. */
public static final int SCAN_MODE_LOW_LATENCY = 2;
/** Scan in balanced power mode.
@@ -73,7 +76,9 @@
/* scanType= */ in.readInt(),
/* scanMode= */ in.readInt(),
/* enableBle= */ in.readBoolean(),
- /* workSource= */ in.readTypedObject(WorkSource.CREATOR));
+ /* workSource= */ in.readTypedObject(WorkSource.CREATOR),
+ /* scanFilters= */
+ in.readArrayList(ScanFilter.class.getClassLoader(), ScanFilter.class));
}
@Override
@@ -81,17 +86,20 @@
return new ScanRequest[size];
}
};
+
private final @ScanType int mScanType;
private final @ScanMode int mScanMode;
private final boolean mEnableBle;
private final @NonNull WorkSource mWorkSource;
+ private final List<ScanFilter> mScanFilters;
private ScanRequest(@ScanType int scanType, @ScanMode int scanMode, boolean enableBle,
- @NonNull WorkSource workSource) {
+ @NonNull WorkSource workSource, List<ScanFilter> scanFilters) {
mScanType = scanType;
mScanMode = scanMode;
mEnableBle = enableBle;
mWorkSource = workSource;
+ mScanFilters = scanFilters;
}
/**
@@ -157,6 +165,16 @@
}
/**
+ * Returns Scan Filters for this request.
+ *
+ * @hide
+ */
+ @NonNull
+ public List<ScanFilter> getScanFilters() {
+ return mScanFilters;
+ }
+
+ /**
* Returns the work source used for power attribution of this request.
*
* @hide
@@ -186,6 +204,7 @@
stringBuilder.append(", scanMode=").append(scanModeToString(mScanMode));
stringBuilder.append(", enableBle=").append(mEnableBle);
stringBuilder.append(", workSource=").append(mWorkSource);
+ stringBuilder.append(", scanFilters=").append(mScanFilters);
stringBuilder.append("]");
return stringBuilder.toString();
}
@@ -196,6 +215,7 @@
dest.writeInt(mScanMode);
dest.writeBoolean(mEnableBle);
dest.writeTypedObject(mWorkSource, /* parcelableFlags= */0);
+ dest.writeTypedList(mScanFilters);
}
@Override
@@ -237,12 +257,14 @@
private boolean mEnableBle;
private WorkSource mWorkSource;
+ private List<ScanFilter> mScanFilters;
/** Creates a new Builder with the given scan type. */
public Builder() {
mScanType = INVALID_SCAN_TYPE;
mEnableBle = true;
mWorkSource = new WorkSource();
+ mScanFilters = new ArrayList<>();
}
/**
@@ -304,6 +326,24 @@
}
/**
+ * Adds a scan filter to the request. Client can call this method multiple times to add
+ * more than one scan filter. Scan results that match any of these scan filters will
+ * be returned.
+ *
+ * <p>On devices with hardware support, scan filters can significantly improve the battery
+ * usage of Nearby scans.
+ *
+ * @param scanFilter Filter for scanning the request.
+ *
+ * @hide
+ */
+ @NonNull
+ public Builder addScanFilter(@NonNull ScanFilter scanFilter) {
+ mScanFilters.add(scanFilter);
+ return this;
+ }
+
+ /**
* Builds a scan request from this builder.
*
* @return a new nearby scan request.
@@ -318,7 +358,7 @@
Preconditions.checkState(isValidScanMode(mScanMode),
"invalid scan mode : " + mScanMode
+ ", scan mode must be one of ScanMode#SCAN_MODE_");
- return new ScanRequest(mScanType, mScanMode, mEnableBle, mWorkSource);
+ return new ScanRequest(mScanType, mScanMode, mEnableBle, mWorkSource, mScanFilters);
}
}
}
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 a7ce771..0151543 100644
--- a/nearby/service/java/com/android/server/nearby/fastpair/FastPairAdvHandler.java
+++ b/nearby/service/java/com/android/server/nearby/fastpair/FastPairAdvHandler.java
@@ -16,11 +16,13 @@
package com.android.server.nearby.fastpair;
+import android.annotation.Nullable;
import android.content.Context;
import android.nearby.FastPairDevice;
import android.nearby.NearbyDevice;
import android.util.Log;
+import com.android.server.nearby.common.bloomfilter.BloomFilter;
import com.android.server.nearby.common.locator.Locator;
import com.android.server.nearby.fastpair.halfsheet.FastPairHalfSheetManager;
import com.android.server.nearby.provider.FastPairDataProvider;
@@ -29,6 +31,8 @@
import com.google.protobuf.ByteString;
+import java.util.List;
+
import service.proto.Cache;
import service.proto.Rpcs;
@@ -87,4 +91,21 @@
// Start to process bloomfilter
}
}
+
+ /**
+ * Checks the bloom filter to see if any of the devices are recognized and should have a
+ * notification displayed for them. A device is recognized if the account key + salt combination
+ * is inside the bloom filter.
+ */
+ @Nullable
+ static FastPairDevice findRecognizedDevice(
+ List<FastPairDevice> devices, BloomFilter bloomFilter, byte[] salt) {
+ for (FastPairDevice device : devices) {
+ // byte[] rotatedKey = concat(device.getAccountKey().toByteArray(), salt);
+// if (bloomFilter.possiblyContains(rotatedKey)) {
+// return device;
+// }
+ }
+ return null;
+ }
}
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 d59e696..34db620 100644
--- a/nearby/service/java/com/android/server/nearby/provider/FastPairDataProvider.java
+++ b/nearby/service/java/com/android/server/nearby/provider/FastPairDataProvider.java
@@ -20,7 +20,6 @@
import android.annotation.Nullable;
import android.content.Context;
import android.nearby.FastPairDataProviderBase;
-import android.nearby.FastPairDevice;
import android.nearby.aidl.FastPairAntispoofkeyDeviceMetadataRequestParcel;
import android.nearby.aidl.FastPairEligibleAccountsRequestParcel;
import android.nearby.aidl.FastPairManageAccountDeviceRequestParcel;
@@ -34,6 +33,7 @@
import java.util.List;
+import service.proto.Data;
import service.proto.Rpcs;
/**
@@ -51,7 +51,6 @@
* Initializes FastPairDataProvider singleton.
*/
public static synchronized FastPairDataProvider init(Context context) {
-
if (sInstance == null) {
sInstance = new FastPairDataProvider(context);
}
@@ -135,8 +134,9 @@
/**
* Get recognized device from bloom filter.
*/
- public FastPairDevice getRecognizedDevice(BloomFilter bloomFilter, byte[] salt) {
- return new FastPairDevice.Builder().build();
+ public Data.FastPairDeviceWithAccountKey getRecognizedDevice(BloomFilter bloomFilter,
+ byte[] salt) {
+ return Data.FastPairDeviceWithAccountKey.newBuilder().build();
}
/**
diff --git a/nearby/service/proto/src/fastpair/data.proto b/nearby/service/proto/src/fastpair/data.proto
new file mode 100644
index 0000000..37dfac2
--- /dev/null
+++ b/nearby/service/proto/src/fastpair/data.proto
@@ -0,0 +1,25 @@
+syntax = "proto3";
+
+package service.proto;
+
+// A device that has been Fast Paired with.
+message FastPairDeviceWithAccountKey {
+ // The account key which was written to the device after pairing completed.
+ bytes account_key = 1;
+
+ // The stored discovery item which represents the notification that should be
+ // associated with the device. Note, this is stored as a raw byte array
+ // instead of StoredDiscoveryItem because icing only supports proto lite and
+ // StoredDiscoveryItem is handed around as a nano proto in implementation,
+ // which are not compatible with each other.
+ bytes discovery_item_bytes = 3;
+
+ // SHA256 of "account key + headset's public address", this is used to
+ // identify the paired headset. Because of adding account key to generate the
+ // hash value, it makes the information anonymous, even for the same headset,
+ // different accounts have different values.
+ bytes sha256_account_key_public_address = 4;
+
+ // Deprecated fields.
+ reserved 2;
+}
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 b5939f8..3bb348b 100644
--- a/nearby/tests/cts/fastpair/src/android/nearby/cts/ScanRequestTest.java
+++ b/nearby/tests/cts/fastpair/src/android/nearby/cts/ScanRequestTest.java
@@ -89,7 +89,8 @@
assertThat(request.toString()).isEqualTo(
"Request[scanType=2, scanMode=SCAN_MODE_BALANCED, "
- + "enableBle=true, workSource=WorkSource{" + UID + " " + APP_NAME + "}]");
+ + "enableBle=true, workSource=WorkSource{" + UID + " " + APP_NAME
+ + "}, scanFilters=[]]");
}
/** Verify toString works correctly with null WorkSource. */
@@ -100,7 +101,8 @@
SCAN_TYPE_FAST_PAIR).setWorkSource(null).build();
assertThat(request.toString()).isEqualTo("Request[scanType=1, "
- + "scanMode=SCAN_MODE_LOW_POWER, enableBle=true, workSource=WorkSource{}]");
+ + "scanMode=SCAN_MODE_LOW_POWER, enableBle=true, workSource=WorkSource{}, "
+ + "scanFilters=[]]");
}
@Test
diff --git a/nearby/tests/unit/src/android/nearby/ScanRequestTest.java b/nearby/tests/unit/src/android/nearby/ScanRequestTest.java
index fdb6db1..509fa1e 100644
--- a/nearby/tests/unit/src/android/nearby/ScanRequestTest.java
+++ b/nearby/tests/unit/src/android/nearby/ScanRequestTest.java
@@ -114,7 +114,8 @@
assertThat(request.toString()).isEqualTo(
"Request[scanType=2, scanMode=SCAN_MODE_BALANCED, "
- + "enableBle=true, workSource=WorkSource{1001 android.nearby.tests}]");
+ + "enableBle=true, workSource=WorkSource{1001 android.nearby.tests}, "
+ + "scanFilters=[]]");
}
/** Verify toString works correctly with null WorkSource. */
@@ -124,7 +125,8 @@
SCAN_TYPE_FAST_PAIR).setWorkSource(null).build();
assertThat(request.toString()).isEqualTo("Request[scanType=1, "
- + "scanMode=SCAN_MODE_LOW_POWER, enableBle=true, workSource=WorkSource{}]");
+ + "scanMode=SCAN_MODE_LOW_POWER, enableBle=true, workSource=WorkSource{}, "
+ + "scanFilters=[]]");
}
/** Verify writing and reading from parcel for scan request. */