Add CDM API to filter by BSSID bitmask
Per recommendation from wifi team, this is an important filter to provide
Test: manual
Fixes: 143313206
Change-Id: Ifcad0f6ce5134854114aa9df97b2c44ece858a30
diff --git a/api/current.txt b/api/current.txt
index 71dc58b..5d532d4 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -9230,14 +9230,16 @@
public final class WifiDeviceFilter implements android.companion.DeviceFilter<android.net.wifi.ScanResult> {
method public int describeContents();
- method public void writeToParcel(android.os.Parcel, int);
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.companion.WifiDeviceFilter> CREATOR;
}
public static final class WifiDeviceFilter.Builder {
ctor public WifiDeviceFilter.Builder();
method @NonNull public android.companion.WifiDeviceFilter build();
- method public android.companion.WifiDeviceFilter.Builder setNamePattern(@Nullable java.util.regex.Pattern);
+ method @NonNull public android.companion.WifiDeviceFilter.Builder setBssid(@Nullable android.net.MacAddress);
+ method @NonNull public android.companion.WifiDeviceFilter.Builder setBssidMask(@NonNull android.net.MacAddress);
+ method @NonNull public android.companion.WifiDeviceFilter.Builder setNamePattern(@Nullable java.util.regex.Pattern);
}
}
diff --git a/core/java/android/companion/WifiDeviceFilter.java b/core/java/android/companion/WifiDeviceFilter.java
index 62098d5..58bf874 100644
--- a/core/java/android/companion/WifiDeviceFilter.java
+++ b/core/java/android/companion/WifiDeviceFilter.java
@@ -17,17 +17,18 @@
package android.companion;
import static android.companion.BluetoothDeviceFilterUtils.getDeviceDisplayNameInternal;
-import static android.companion.BluetoothDeviceFilterUtils.patternFromString;
-import static android.companion.BluetoothDeviceFilterUtils.patternToString;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.SuppressLint;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.le.ScanFilter;
+import android.net.MacAddress;
import android.net.wifi.ScanResult;
import android.os.Parcel;
-import android.provider.OneTimeUseBuilder;
+import android.os.Parcelable;
+
+import com.android.internal.util.DataClass;
+import com.android.internal.util.Parcelling;
import java.util.Objects;
import java.util.regex.Pattern;
@@ -37,30 +38,38 @@
*
* @see ScanFilter
*/
+@DataClass(
+ genParcelable = true,
+ genAidl = false,
+ genBuilder = true,
+ genEqualsHashCode = true,
+ genHiddenGetters = true)
public final class WifiDeviceFilter implements DeviceFilter<ScanResult> {
- private final Pattern mNamePattern;
+ /**
+ * If set, only devices with {@link BluetoothDevice#getName name} matching the given regular
+ * expression will be shown
+ */
+ @DataClass.ParcelWith(Parcelling.BuiltIn.ForPattern.class)
+ private @Nullable Pattern mNamePattern = null;
- private WifiDeviceFilter(Pattern namePattern) {
- mNamePattern = namePattern;
- }
+ /**
+ * If set, only devices with BSSID matching the given one will be shown
+ */
+ private @Nullable MacAddress mBssid = null;
- @SuppressLint("ParcelClassLoader")
- private WifiDeviceFilter(Parcel in) {
- this(patternFromString(in.readString()));
- }
-
- /** @hide */
- @Nullable
- public Pattern getNamePattern() {
- return mNamePattern;
- }
-
+ /**
+ * If set, only bits at positions set in this mask, will be compared to the given
+ * {@link Builder#setBssid BSSID} filter.
+ */
+ private @NonNull MacAddress mBssidMask = MacAddress.BROADCAST_ADDRESS;
/** @hide */
@Override
public boolean matches(ScanResult device) {
- return BluetoothDeviceFilterUtils.matchesName(getNamePattern(), device);
+ return BluetoothDeviceFilterUtils.matchesName(getNamePattern(), device)
+ && (mBssid == null
+ || MacAddress.fromString(device.BSSID).matches(mBssid, mBssidMask));
}
/** @hide */
@@ -75,65 +84,249 @@
return MEDIUM_TYPE_WIFI;
}
+
+
+ // Code below generated by codegen v1.0.11.
+ //
+ // DO NOT MODIFY!
+ // CHECKSTYLE:OFF Generated code
+ //
+ // To regenerate run:
+ // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/companion/WifiDeviceFilter.java
+ //
+ // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+ // Settings > Editor > Code Style > Formatter Control
+ //@formatter:off
+
+
+ @DataClass.Generated.Member
+ /* package-private */ WifiDeviceFilter(
+ @Nullable Pattern namePattern,
+ @Nullable MacAddress bssid,
+ @NonNull MacAddress bssidMask) {
+ this.mNamePattern = namePattern;
+ this.mBssid = bssid;
+ this.mBssidMask = bssidMask;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mBssidMask);
+
+ // onConstructed(); // You can define this method to get a callback
+ }
+
+ /**
+ * If set, only devices with {@link BluetoothDevice#getName name} matching the given regular
+ * expression will be shown
+ *
+ * @hide
+ */
+ @DataClass.Generated.Member
+ public @Nullable Pattern getNamePattern() {
+ return mNamePattern;
+ }
+
+ /**
+ * If set, only devices with BSSID matching the given one will be shown
+ *
+ * @hide
+ */
+ @DataClass.Generated.Member
+ public @Nullable MacAddress getBssid() {
+ return mBssid;
+ }
+
+ /**
+ * If set, only bits at positions set in this mask, will be compared to the given
+ * {@link Builder#setBssid BSSID} filter.
+ *
+ * @hide
+ */
+ @DataClass.Generated.Member
+ public @NonNull MacAddress getBssidMask() {
+ return mBssidMask;
+ }
+
@Override
- public boolean equals(Object o) {
+ @DataClass.Generated.Member
+ public boolean equals(@Nullable Object o) {
+ // You can override field equality logic by defining either of the methods like:
+ // boolean fieldNameEquals(WifiDeviceFilter other) { ... }
+ // boolean fieldNameEquals(FieldType otherValue) { ... }
+
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
+ @SuppressWarnings("unchecked")
WifiDeviceFilter that = (WifiDeviceFilter) o;
- return Objects.equals(mNamePattern, that.mNamePattern);
+ //noinspection PointlessBooleanExpression
+ return true
+ && Objects.equals(mNamePattern, that.mNamePattern)
+ && Objects.equals(mBssid, that.mBssid)
+ && Objects.equals(mBssidMask, that.mBssidMask);
}
@Override
+ @DataClass.Generated.Member
public int hashCode() {
- return Objects.hash(mNamePattern);
+ // You can override field hashCode logic by defining methods like:
+ // int fieldNameHashCode() { ... }
+
+ int _hash = 1;
+ _hash = 31 * _hash + Objects.hashCode(mNamePattern);
+ _hash = 31 * _hash + Objects.hashCode(mBssid);
+ _hash = 31 * _hash + Objects.hashCode(mBssidMask);
+ return _hash;
}
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeString(patternToString(getNamePattern()));
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- public static final @android.annotation.NonNull Creator<WifiDeviceFilter> CREATOR
- = new Creator<WifiDeviceFilter>() {
- @Override
- public WifiDeviceFilter createFromParcel(Parcel in) {
- return new WifiDeviceFilter(in);
+ @DataClass.Generated.Member
+ static Parcelling<Pattern> sParcellingForNamePattern =
+ Parcelling.Cache.get(
+ Parcelling.BuiltIn.ForPattern.class);
+ static {
+ if (sParcellingForNamePattern == null) {
+ sParcellingForNamePattern = Parcelling.Cache.put(
+ new Parcelling.BuiltIn.ForPattern());
}
+ }
+ @Override
+ @DataClass.Generated.Member
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ // You can override field parcelling by defining methods like:
+ // void parcelFieldName(Parcel dest, int flags) { ... }
+
+ byte flg = 0;
+ if (mNamePattern != null) flg |= 0x1;
+ if (mBssid != null) flg |= 0x2;
+ dest.writeByte(flg);
+ sParcellingForNamePattern.parcel(mNamePattern, dest, flags);
+ if (mBssid != null) dest.writeTypedObject(mBssid, flags);
+ dest.writeTypedObject(mBssidMask, flags);
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public int describeContents() { return 0; }
+
+ /** @hide */
+ @SuppressWarnings({"unchecked", "RedundantCast"})
+ @DataClass.Generated.Member
+ /* package-private */ WifiDeviceFilter(@NonNull Parcel in) {
+ // You can override field unparcelling by defining methods like:
+ // static FieldType unparcelFieldName(Parcel in) { ... }
+
+ byte flg = in.readByte();
+ Pattern namePattern = sParcellingForNamePattern.unparcel(in);
+ MacAddress bssid = (flg & 0x2) == 0 ? null : (MacAddress) in.readTypedObject(MacAddress.CREATOR);
+ MacAddress bssidMask = (MacAddress) in.readTypedObject(MacAddress.CREATOR);
+
+ this.mNamePattern = namePattern;
+ this.mBssid = bssid;
+ this.mBssidMask = bssidMask;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mBssidMask);
+
+ // onConstructed(); // You can define this method to get a callback
+ }
+
+ @DataClass.Generated.Member
+ public static final @NonNull Parcelable.Creator<WifiDeviceFilter> CREATOR
+ = new Parcelable.Creator<WifiDeviceFilter>() {
@Override
public WifiDeviceFilter[] newArray(int size) {
return new WifiDeviceFilter[size];
}
+
+ @Override
+ public WifiDeviceFilter createFromParcel(@NonNull Parcel in) {
+ return new WifiDeviceFilter(in);
+ }
};
/**
- * Builder for {@link WifiDeviceFilter}
+ * A builder for {@link WifiDeviceFilter}
*/
- public static final class Builder extends OneTimeUseBuilder<WifiDeviceFilter> {
- private Pattern mNamePattern;
+ @SuppressWarnings("WeakerAccess")
+ @DataClass.Generated.Member
+ public static final class Builder {
+
+ private @Nullable Pattern mNamePattern;
+ private @Nullable MacAddress mBssid;
+ private @NonNull MacAddress mBssidMask;
+
+ private long mBuilderFieldsSet = 0L;
+
+ public Builder() {
+ }
/**
- * @param regex if set, only devices with {@link BluetoothDevice#getName name} matching the
- * given regular expression will be shown
- * @return self for chaining
+ * If set, only devices with {@link BluetoothDevice#getName name} matching the given regular
+ * expression will be shown
*/
- public Builder setNamePattern(@Nullable Pattern regex) {
+ @DataClass.Generated.Member
+ public @NonNull Builder setNamePattern(@Nullable Pattern value) {
checkNotUsed();
- mNamePattern = regex;
+ mBuilderFieldsSet |= 0x1;
+ mNamePattern = value;
return this;
}
- /** @inheritDoc */
- @Override
- @NonNull
- public WifiDeviceFilter build() {
- markUsed();
- return new WifiDeviceFilter(mNamePattern);
+ /**
+ * If set, only devices with BSSID matching the given one will be shown
+ */
+ @DataClass.Generated.Member
+ public @NonNull Builder setBssid(@Nullable MacAddress value) {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x2;
+ mBssid = value;
+ return this;
+ }
+
+ /**
+ * If set, only bits at positions set in this mask, will be compared to the given
+ * {@link Builder#setBssid BSSID} filter.
+ */
+ @DataClass.Generated.Member
+ public @NonNull Builder setBssidMask(@NonNull MacAddress value) {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x4;
+ mBssidMask = value;
+ return this;
+ }
+
+ /** Builds the instance. This builder should not be touched after calling this! */
+ public @NonNull WifiDeviceFilter build() {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x8; // Mark builder used
+
+ if ((mBuilderFieldsSet & 0x1) == 0) {
+ mNamePattern = null;
+ }
+ if ((mBuilderFieldsSet & 0x2) == 0) {
+ mBssid = null;
+ }
+ if ((mBuilderFieldsSet & 0x4) == 0) {
+ mBssidMask = MacAddress.BROADCAST_ADDRESS;
+ }
+ WifiDeviceFilter o = new WifiDeviceFilter(
+ mNamePattern,
+ mBssid,
+ mBssidMask);
+ return o;
+ }
+
+ private void checkNotUsed() {
+ if ((mBuilderFieldsSet & 0x8) != 0) {
+ throw new IllegalStateException(
+ "This Builder should not be reused. Use a new Builder instance instead");
+ }
}
}
+
+ @DataClass.Generated(
+ time = 1571960300742L,
+ codegenVersion = "1.0.11",
+ sourceFile = "frameworks/base/core/java/android/companion/WifiDeviceFilter.java",
+ inputSignatures = "private @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForPattern.class) @android.annotation.Nullable java.util.regex.Pattern mNamePattern\nprivate @android.annotation.Nullable android.net.MacAddress mBssid\nprivate @android.annotation.NonNull android.net.MacAddress mBssidMask\npublic @java.lang.Override boolean matches(android.net.wifi.ScanResult)\npublic @java.lang.Override java.lang.String getDeviceDisplayName(android.net.wifi.ScanResult)\npublic @java.lang.Override int getMediumType()\nclass WifiDeviceFilter extends java.lang.Object implements [android.companion.DeviceFilter<android.net.wifi.ScanResult>]\n@com.android.internal.util.DataClass(genParcelable=true, genAidl=false, genBuilder=true, genEqualsHashCode=true, genHiddenGetters=true)")
+ @Deprecated
+ private void __metadata() {}
+
}
diff --git a/tools/codegen/src/com/android/codegen/Generators.kt b/tools/codegen/src/com/android/codegen/Generators.kt
index 431f378..bd32f9c 100644
--- a/tools/codegen/src/com/android/codegen/Generators.kt
+++ b/tools/codegen/src/com/android/codegen/Generators.kt
@@ -212,13 +212,15 @@
"Object"
}
+ val maybeFinal = if_(classAst.isFinal, "final ")
+
+"/**"
+" * A builder for {@link $ClassName}"
if (FeatureFlag.BUILDER.hidden) +" * @hide"
+" */"
+"@SuppressWarnings(\"WeakerAccess\")"
+GENERATED_MEMBER_HEADER
- !"public static class $BuilderClass$genericArgs"
+ !"public static ${maybeFinal}class $BuilderClass$genericArgs"
if (BuilderSupertype != "Object") {
appendSameLine(" extends $BuilderSupertype")
}
@@ -359,7 +361,7 @@
private fun ClassPrinter.generateBuilderBuild() {
+"/** Builds the instance. This builder should not be touched after calling this! */"
- "public $ClassType build()" {
+ "public @$NonNull $ClassType build()" {
+"checkNotUsed();"
+"mBuilderFieldsSet |= ${bitAtExpr(fields.size)}; // Mark builder used"
+""
diff --git a/tools/codegen/src/com/android/codegen/SharedConstants.kt b/tools/codegen/src/com/android/codegen/SharedConstants.kt
index 3eb9e7b..270d34a 100644
--- a/tools/codegen/src/com/android/codegen/SharedConstants.kt
+++ b/tools/codegen/src/com/android/codegen/SharedConstants.kt
@@ -1,7 +1,7 @@
package com.android.codegen
const val CODEGEN_NAME = "codegen"
-const val CODEGEN_VERSION = "1.0.9"
+const val CODEGEN_VERSION = "1.0.11"
const val CANONICAL_BUILDER_CLASS = "Builder"
const val BASE_BUILDER_CLASS = "BaseBuilder"