diff options
19 files changed, 214 insertions, 730 deletions
diff --git a/api/current.txt b/api/current.txt index 0d38bc6e3d56..1a5ea853b365 100644 --- a/api/current.txt +++ b/api/current.txt @@ -8183,17 +8183,18 @@ package android.bluetooth.le { package android.companion { - public final class AssociationRequest implements android.os.Parcelable { + public final class AssociationRequest<F extends android.companion.DeviceFilter> implements android.os.Parcelable { method public int describeContents(); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator<android.companion.AssociationRequest> CREATOR; } - public static final class AssociationRequest.Builder { - ctor public AssociationRequest.Builder(); - method public android.companion.AssociationRequest.Builder addDeviceFilter(android.companion.DeviceFilter<?>); - method public android.companion.AssociationRequest build(); - method public android.companion.AssociationRequest.Builder setSingleDevice(boolean); + public static final class AssociationRequest.Builder<F extends android.companion.DeviceFilter> { + method public android.companion.AssociationRequest<F> build(); + method public static android.companion.AssociationRequest.Builder<android.companion.BluetoothDeviceFilter> createForBluetoothDevice(); + method public static android.companion.AssociationRequest.Builder<android.companion.BluetoothLEDeviceFilter> createForBluetoothLEDevice(); + method public android.companion.AssociationRequest.Builder<F> setDeviceFilter(F); + method public android.companion.AssociationRequest.Builder<F> setSingleDevice(boolean); } public final class BluetoothDeviceFilter implements android.companion.DeviceFilter { @@ -8214,20 +8215,17 @@ package android.companion { method public int describeContents(); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator<android.companion.BluetoothLEDeviceFilter> CREATOR; - field public static final int RENAME_PREFIX_LENGTH_LIMIT = 10; // 0xa } public static final class BluetoothLEDeviceFilter.Builder { ctor public BluetoothLEDeviceFilter.Builder(); method public android.companion.BluetoothLEDeviceFilter build(); method public android.companion.BluetoothLEDeviceFilter.Builder setNamePattern(java.util.regex.Pattern); - method public android.companion.BluetoothLEDeviceFilter.Builder setRawDataFilter(byte[], byte[]); - method public android.companion.BluetoothLEDeviceFilter.Builder setRename(java.lang.String, java.lang.String, int, int, boolean); method public android.companion.BluetoothLEDeviceFilter.Builder setScanFilter(android.bluetooth.le.ScanFilter); } public final class CompanionDeviceManager { - method public void associate(android.companion.AssociationRequest, android.companion.CompanionDeviceManager.Callback, android.os.Handler); + method public void associate(android.companion.AssociationRequest<?>, android.companion.CompanionDeviceManager.Callback, android.os.Handler); method public void disassociate(java.lang.String); method public java.util.List<java.lang.String> getAssociations(); field public static final java.lang.String EXTRA_DEVICE = "android.companion.extra.DEVICE"; @@ -8242,18 +8240,6 @@ package android.companion { public abstract interface DeviceFilter<D extends android.os.Parcelable> implements android.os.Parcelable { } - public final class WifiDeviceFilter implements android.companion.DeviceFilter { - method public int describeContents(); - method public void writeToParcel(android.os.Parcel, int); - field public static final android.os.Parcelable.Creator<android.companion.WifiDeviceFilter> CREATOR; - } - - public static final class WifiDeviceFilter.Builder { - ctor public WifiDeviceFilter.Builder(); - method public android.companion.WifiDeviceFilter build(); - method public android.companion.WifiDeviceFilter.Builder setNamePattern(java.util.regex.Pattern); - } - } package android.content { diff --git a/api/system-current.txt b/api/system-current.txt index 16de51039ff4..b5c20e52e913 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -8683,17 +8683,18 @@ package android.bluetooth.le { package android.companion { - public final class AssociationRequest implements android.os.Parcelable { + public final class AssociationRequest<F extends android.companion.DeviceFilter> implements android.os.Parcelable { method public int describeContents(); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator<android.companion.AssociationRequest> CREATOR; } - public static final class AssociationRequest.Builder { - ctor public AssociationRequest.Builder(); - method public android.companion.AssociationRequest.Builder addDeviceFilter(android.companion.DeviceFilter<?>); - method public android.companion.AssociationRequest build(); - method public android.companion.AssociationRequest.Builder setSingleDevice(boolean); + public static final class AssociationRequest.Builder<F extends android.companion.DeviceFilter> { + method public android.companion.AssociationRequest<F> build(); + method public static android.companion.AssociationRequest.Builder<android.companion.BluetoothDeviceFilter> createForBluetoothDevice(); + method public static android.companion.AssociationRequest.Builder<android.companion.BluetoothLEDeviceFilter> createForBluetoothLEDevice(); + method public android.companion.AssociationRequest.Builder<F> setDeviceFilter(F); + method public android.companion.AssociationRequest.Builder<F> setSingleDevice(boolean); } public final class BluetoothDeviceFilter implements android.companion.DeviceFilter { @@ -8714,20 +8715,17 @@ package android.companion { method public int describeContents(); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator<android.companion.BluetoothLEDeviceFilter> CREATOR; - field public static final int RENAME_PREFIX_LENGTH_LIMIT = 10; // 0xa } public static final class BluetoothLEDeviceFilter.Builder { ctor public BluetoothLEDeviceFilter.Builder(); method public android.companion.BluetoothLEDeviceFilter build(); method public android.companion.BluetoothLEDeviceFilter.Builder setNamePattern(java.util.regex.Pattern); - method public android.companion.BluetoothLEDeviceFilter.Builder setRawDataFilter(byte[], byte[]); - method public android.companion.BluetoothLEDeviceFilter.Builder setRename(java.lang.String, java.lang.String, int, int, boolean); method public android.companion.BluetoothLEDeviceFilter.Builder setScanFilter(android.bluetooth.le.ScanFilter); } public final class CompanionDeviceManager { - method public void associate(android.companion.AssociationRequest, android.companion.CompanionDeviceManager.Callback, android.os.Handler); + method public void associate(android.companion.AssociationRequest<?>, android.companion.CompanionDeviceManager.Callback, android.os.Handler); method public void disassociate(java.lang.String); method public java.util.List<java.lang.String> getAssociations(); field public static final java.lang.String EXTRA_DEVICE = "android.companion.extra.DEVICE"; @@ -8742,18 +8740,6 @@ package android.companion { public abstract interface DeviceFilter<D extends android.os.Parcelable> implements android.os.Parcelable { } - public final class WifiDeviceFilter implements android.companion.DeviceFilter { - method public int describeContents(); - method public void writeToParcel(android.os.Parcel, int); - field public static final android.os.Parcelable.Creator<android.companion.WifiDeviceFilter> CREATOR; - } - - public static final class WifiDeviceFilter.Builder { - ctor public WifiDeviceFilter.Builder(); - method public android.companion.WifiDeviceFilter build(); - method public android.companion.WifiDeviceFilter.Builder setNamePattern(java.util.regex.Pattern); - } - } package android.content { diff --git a/api/test-current.txt b/api/test-current.txt index 62f76bde349d..57cc998ffb5d 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -8210,17 +8210,18 @@ package android.bluetooth.le { package android.companion { - public final class AssociationRequest implements android.os.Parcelable { + public final class AssociationRequest<F extends android.companion.DeviceFilter> implements android.os.Parcelable { method public int describeContents(); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator<android.companion.AssociationRequest> CREATOR; } - public static final class AssociationRequest.Builder { - ctor public AssociationRequest.Builder(); - method public android.companion.AssociationRequest.Builder addDeviceFilter(android.companion.DeviceFilter<?>); - method public android.companion.AssociationRequest build(); - method public android.companion.AssociationRequest.Builder setSingleDevice(boolean); + public static final class AssociationRequest.Builder<F extends android.companion.DeviceFilter> { + method public android.companion.AssociationRequest<F> build(); + method public static android.companion.AssociationRequest.Builder<android.companion.BluetoothDeviceFilter> createForBluetoothDevice(); + method public static android.companion.AssociationRequest.Builder<android.companion.BluetoothLEDeviceFilter> createForBluetoothLEDevice(); + method public android.companion.AssociationRequest.Builder<F> setDeviceFilter(F); + method public android.companion.AssociationRequest.Builder<F> setSingleDevice(boolean); } public final class BluetoothDeviceFilter implements android.companion.DeviceFilter { @@ -8241,20 +8242,17 @@ package android.companion { method public int describeContents(); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator<android.companion.BluetoothLEDeviceFilter> CREATOR; - field public static final int RENAME_PREFIX_LENGTH_LIMIT = 10; // 0xa } public static final class BluetoothLEDeviceFilter.Builder { ctor public BluetoothLEDeviceFilter.Builder(); method public android.companion.BluetoothLEDeviceFilter build(); method public android.companion.BluetoothLEDeviceFilter.Builder setNamePattern(java.util.regex.Pattern); - method public android.companion.BluetoothLEDeviceFilter.Builder setRawDataFilter(byte[], byte[]); - method public android.companion.BluetoothLEDeviceFilter.Builder setRename(java.lang.String, java.lang.String, int, int, boolean); method public android.companion.BluetoothLEDeviceFilter.Builder setScanFilter(android.bluetooth.le.ScanFilter); } public final class CompanionDeviceManager { - method public void associate(android.companion.AssociationRequest, android.companion.CompanionDeviceManager.Callback, android.os.Handler); + method public void associate(android.companion.AssociationRequest<?>, android.companion.CompanionDeviceManager.Callback, android.os.Handler); method public void disassociate(java.lang.String); method public java.util.List<java.lang.String> getAssociations(); field public static final java.lang.String EXTRA_DEVICE = "android.companion.extra.DEVICE"; @@ -8269,18 +8267,6 @@ package android.companion { public abstract interface DeviceFilter<D extends android.os.Parcelable> implements android.os.Parcelable { } - public final class WifiDeviceFilter implements android.companion.DeviceFilter { - method public int describeContents(); - method public void writeToParcel(android.os.Parcel, int); - field public static final android.os.Parcelable.Creator<android.companion.WifiDeviceFilter> CREATOR; - } - - public static final class WifiDeviceFilter.Builder { - ctor public WifiDeviceFilter.Builder(); - method public android.companion.WifiDeviceFilter build(); - method public android.companion.WifiDeviceFilter.Builder setNamePattern(java.util.regex.Pattern); - } - } package android.content { diff --git a/core/java/android/bluetooth/le/ScanFilter.java b/core/java/android/bluetooth/le/ScanFilter.java index 457096bf843e..b89c64a8cac6 100644 --- a/core/java/android/bluetooth/le/ScanFilter.java +++ b/core/java/android/bluetooth/le/ScanFilter.java @@ -23,8 +23,6 @@ import android.os.Parcel; import android.os.ParcelUuid; import android.os.Parcelable; -import com.android.internal.util.BitUtils; - import java.util.Arrays; import java.util.List; import java.util.Objects; @@ -347,7 +345,15 @@ public final class ScanFilter implements Parcelable { // Check if the uuid pattern matches the particular service uuid. private static boolean matchesServiceUuid(UUID uuid, UUID mask, UUID data) { - return BitUtils.maskedEquals(data, uuid, mask); + if (mask == null) { + return uuid.equals(data); + } + if ((uuid.getLeastSignificantBits() & mask.getLeastSignificantBits()) != + (data.getLeastSignificantBits() & mask.getLeastSignificantBits())) { + return false; + } + return ((uuid.getMostSignificantBits() & mask.getMostSignificantBits()) == + (data.getMostSignificantBits() & mask.getMostSignificantBits())); } // Check whether the data pattern matches the parsed data. diff --git a/core/java/android/companion/AssociationRequest.java b/core/java/android/companion/AssociationRequest.java index 56f5d4483270..d477f43ac8c2 100644 --- a/core/java/android/companion/AssociationRequest.java +++ b/core/java/android/companion/AssociationRequest.java @@ -16,21 +16,20 @@ package android.companion; +import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.os.Parcel; import android.os.Parcelable; import android.provider.OneTimeUseBuilder; -import com.android.internal.util.ArrayUtils; - -import java.util.ArrayList; -import java.util.List; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; /** * A request for the user to select a companion device to associate with. * - * You can optionally set {@link Builder#addDeviceFilter filters} for which devices to show to the + * You can optionally set a {@link Builder#setDeviceFilter filter} for which devices to show to the * user to select from. * The exact type and fields of the filter you can set depend on the * medium type. See {@link Builder}'s static factory methods for specific protocols that are @@ -38,22 +37,38 @@ import java.util.List; * * You can also set {@link Builder#setSingleDevice single device} to request a popup with single * device to be shown instead of a list to choose from + * + * @param <F> Device filter type */ -public final class AssociationRequest implements Parcelable { +public final class AssociationRequest<F extends DeviceFilter> implements Parcelable { + + /** @hide */ + public static final int MEDIUM_TYPE_BLUETOOTH = 0; + /** @hide */ + public static final int MEDIUM_TYPE_BLUETOOTH_LE = 1; + /** @hide */ + public static final int MEDIUM_TYPE_WIFI = 2; + + /** @hide */ + @IntDef({MEDIUM_TYPE_BLUETOOTH, MEDIUM_TYPE_BLUETOOTH_LE, MEDIUM_TYPE_WIFI}) + @Retention(RetentionPolicy.SOURCE) + public @interface MediumType {} private final boolean mSingleDevice; - private final List<DeviceFilter<?>> mDeviceFilters; + private final int mMediumType; + private final F mDeviceFilter; - private AssociationRequest( - boolean singleDevice, @Nullable List<DeviceFilter<?>> deviceFilters) { + private AssociationRequest(boolean singleDevice, int mMediumType, F deviceFilter) { this.mSingleDevice = singleDevice; - this.mDeviceFilters = ArrayUtils.emptyIfNull(deviceFilters); + this.mMediumType = mMediumType; + this.mDeviceFilter = deviceFilter; } private AssociationRequest(Parcel in) { this( in.readByte() != 0, - in.readParcelableList(new ArrayList<>(), AssociationRequest.class.getClassLoader())); + in.readInt(), + in.readParcelable(AssociationRequest.class.getClassLoader())); } /** @hide */ @@ -62,15 +77,22 @@ public final class AssociationRequest implements Parcelable { } /** @hide */ - @NonNull - public List<DeviceFilter<?>> getDeviceFilters() { - return mDeviceFilters; + @MediumType + public int getMediumType() { + return mMediumType; + } + + /** @hide */ + @Nullable + public F getDeviceFilter() { + return mDeviceFilter; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeByte((byte) (mSingleDevice ? 1 : 0)); - dest.writeParcelableList(mDeviceFilters, flags); + dest.writeInt(mMediumType); + dest.writeParcelable(mDeviceFilter, flags); } @Override @@ -92,19 +114,45 @@ public final class AssociationRequest implements Parcelable { /** * A builder for {@link AssociationRequest} + * + * @param <F> the type of filter for the request. */ - public static final class Builder extends OneTimeUseBuilder<AssociationRequest> { + public static final class Builder<F extends DeviceFilter> + extends OneTimeUseBuilder<AssociationRequest<F>> { private boolean mSingleDevice = false; - @Nullable private ArrayList<DeviceFilter<?>> mDeviceFilters = null; + @MediumType private int mMediumType; + @Nullable private F mDeviceFilter = null; + + private Builder() {} + + /** + * Create a new builder for an association request with a Bluetooth LE device + */ + @NonNull + public static Builder<BluetoothLEDeviceFilter> createForBluetoothLEDevice() { + return new Builder<BluetoothLEDeviceFilter>() + .setMediumType(MEDIUM_TYPE_BLUETOOTH_LE); + } + + /** + * Create a new builder for an association request with a Bluetooth(non-LE) device + */ + @NonNull + public static Builder<BluetoothDeviceFilter> createForBluetoothDevice() { + return new Builder<BluetoothDeviceFilter>() + .setMediumType(MEDIUM_TYPE_BLUETOOTH); + } - public Builder() {} + //TODO implement, once specific filter classes are available +// public static Builder<> createForWiFiDevice() +// public static Builder<> createForNanDevice() /** * @param singleDevice if true, scanning for a device will stop as soon as at least one * fitting device is found */ @NonNull - public Builder setSingleDevice(boolean singleDevice) { + public Builder<F> setSingleDevice(boolean singleDevice) { checkNotUsed(); this.mSingleDevice = singleDevice; return this; @@ -115,20 +163,29 @@ public final class AssociationRequest implements Parcelable { * user */ @NonNull - public Builder addDeviceFilter(@Nullable DeviceFilter<?> deviceFilter) { + public Builder<F> setDeviceFilter(@Nullable F deviceFilter) { checkNotUsed(); - if (deviceFilter != null) { - mDeviceFilters = ArrayUtils.add(mDeviceFilters, deviceFilter); - } + this.mDeviceFilter = deviceFilter; + return this; + } + + /** + * @param deviceType A type of medium over which to discover devices + * + * @see MediumType + */ + @NonNull + private Builder<F> setMediumType(@MediumType int deviceType) { + mMediumType = deviceType; return this; } /** @inheritDoc */ @NonNull @Override - public AssociationRequest build() { + public AssociationRequest<F> build() { markUsed(); - return new AssociationRequest(mSingleDevice, mDeviceFilters); + return new AssociationRequest<>(mSingleDevice, mMediumType, mDeviceFilter); } } } diff --git a/core/java/android/companion/BluetoothDeviceFilter.java b/core/java/android/companion/BluetoothDeviceFilter.java index 0f16b7b90165..5a69955429aa 100644 --- a/core/java/android/companion/BluetoothDeviceFilter.java +++ b/core/java/android/companion/BluetoothDeviceFilter.java @@ -16,7 +16,6 @@ package android.companion; -import static android.companion.BluetoothDeviceFilterUtils.getDeviceDisplayNameInternal; import static android.companion.BluetoothDeviceFilterUtils.matchesAddress; import static android.companion.BluetoothDeviceFilterUtils.matchesName; import static android.companion.BluetoothDeviceFilterUtils.matchesServiceUuids; @@ -41,6 +40,8 @@ import java.util.regex.Pattern; */ public final class BluetoothDeviceFilter implements DeviceFilter<BluetoothDevice> { + private static BluetoothDeviceFilter NO_OP; + private final Pattern mNamePattern; private final String mAddress; private final List<ParcelUuid> mServiceUuids; @@ -66,27 +67,30 @@ public final class BluetoothDeviceFilter implements DeviceFilter<BluetoothDevice } private static List<ParcelUuid> readUuids(Parcel in) { - return in.readParcelableList(new ArrayList<>(), ParcelUuid.class.getClassLoader()); + final ArrayList<ParcelUuid> list = new ArrayList<>(); + in.readParcelableList(list, ParcelUuid.class.getClassLoader()); + return list; } /** @hide */ - @Override - public boolean matches(BluetoothDevice device) { - return matchesAddress(mAddress, device) - && matchesServiceUuids(mServiceUuids, mServiceUuidMasks, device) - && matchesName(getNamePattern(), device); + @NonNull + public static BluetoothDeviceFilter nullsafe(@Nullable BluetoothDeviceFilter nullable) { + return nullable != null ? nullable : noOp(); } /** @hide */ - @Override - public String getDeviceDisplayName(BluetoothDevice device) { - return getDeviceDisplayNameInternal(device); + @NonNull + public static BluetoothDeviceFilter noOp() { + if (NO_OP == null) NO_OP = new Builder().build(); + return NO_OP; } /** @hide */ @Override - public int getMediumType() { - return DeviceFilter.MEDIUM_TYPE_BLUETOOTH; + public boolean matches(BluetoothDevice device) { + return matchesAddress(mAddress, device) + && matchesServiceUuids(mServiceUuids, mServiceUuidMasks, device) + && matchesName(getNamePattern(), device); } /** @hide */ diff --git a/core/java/android/companion/BluetoothDeviceFilterUtils.java b/core/java/android/companion/BluetoothDeviceFilterUtils.java index 8a316f19af8e..289f9953a068 100644 --- a/core/java/android/companion/BluetoothDeviceFilterUtils.java +++ b/core/java/android/companion/BluetoothDeviceFilterUtils.java @@ -23,9 +23,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.bluetooth.BluetoothDevice; import android.bluetooth.le.ScanFilter; -import android.net.wifi.ScanResult; import android.os.ParcelUuid; -import android.os.Parcelable; import android.util.Log; import java.util.Arrays; @@ -98,47 +96,12 @@ public class BluetoothDeviceFilterUtils { return result; } - static boolean matchesName(@Nullable Pattern namePattern, ScanResult device) { - boolean result; - if (namePattern == null) { - result = true; - } else if (device == null) { - result = false; - } else { - final String name = device.SSID; - result = name != null && namePattern.matcher(name).find(); - } - if (DEBUG) debugLogMatchResult(result, device, namePattern); - return result; - } - private static void debugLogMatchResult( boolean result, BluetoothDevice device, Object criteria) { - Log.i(LOG_TAG, getDeviceDisplayNameInternal(device) + (result ? " ~ " : " !~ ") + criteria); + Log.i(LOG_TAG, getDeviceDisplayName(device) + (result ? " ~ " : " !~ ") + criteria); } - private static void debugLogMatchResult( - boolean result, ScanResult device, Object criteria) { - Log.i(LOG_TAG, getDeviceDisplayNameInternal(device) + (result ? " ~ " : " !~ ") + criteria); - } - - public static String getDeviceDisplayNameInternal(@NonNull BluetoothDevice device) { + public static String getDeviceDisplayName(@NonNull BluetoothDevice device) { return firstNotEmpty(device.getAliasName(), device.getAddress()); } - - public static String getDeviceDisplayNameInternal(@NonNull ScanResult device) { - return firstNotEmpty(device.SSID, device.BSSID); - } - - public static String getDeviceMacAddress(@NonNull Parcelable device) { - if (device instanceof BluetoothDevice) { - return ((BluetoothDevice) device).getAddress(); - } else if (device instanceof ScanResult) { - return ((ScanResult) device).BSSID; - } else if (device instanceof android.bluetooth.le.ScanResult) { - return getDeviceMacAddress(((android.bluetooth.le.ScanResult) device).getDevice()); - } else { - throw new IllegalArgumentException("Unknown device type: " + device); - } - } } diff --git a/core/java/android/companion/BluetoothLEDeviceFilter.java b/core/java/android/companion/BluetoothLEDeviceFilter.java index e057fbcc901a..4a481ca80045 100644 --- a/core/java/android/companion/BluetoothLEDeviceFilter.java +++ b/core/java/android/companion/BluetoothLEDeviceFilter.java @@ -16,25 +16,18 @@ package android.companion; -import static android.companion.BluetoothDeviceFilterUtils.getDeviceDisplayNameInternal; import static android.companion.BluetoothDeviceFilterUtils.patternFromString; import static android.companion.BluetoothDeviceFilterUtils.patternToString; -import static com.android.internal.util.Preconditions.checkArgument; - import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.SuppressLint; import android.bluetooth.BluetoothDevice; import android.bluetooth.le.ScanFilter; -import android.bluetooth.le.ScanRecord; -import android.bluetooth.le.ScanResult; import android.os.Parcel; import android.provider.OneTimeUseBuilder; -import android.text.TextUtils; -import com.android.internal.util.BitUtils; import com.android.internal.util.ObjectUtils; -import com.android.internal.util.Preconditions; import java.util.regex.Pattern; @@ -43,122 +36,57 @@ import java.util.regex.Pattern; * * @see ScanFilter */ -public final class BluetoothLEDeviceFilter implements DeviceFilter<ScanResult> { +public final class BluetoothLEDeviceFilter implements DeviceFilter<BluetoothDevice> { - private static final int RENAME_PREFIX_LENGTH_LIMIT = 10; + private static BluetoothLEDeviceFilter NO_OP; private final Pattern mNamePattern; private final ScanFilter mScanFilter; - private final byte[] mRawDataFilter; - private final byte[] mRawDataFilterMask; - private final String mRenamePrefix; - private final String mRenameSuffix; - private final int mRenameBytesFrom; - private final int mRenameBytesTo; - private final boolean mRenameBytesReverseOrder; - private BluetoothLEDeviceFilter(Pattern namePattern, ScanFilter scanFilter, - byte[] rawDataFilter, byte[] rawDataFilterMask, String renamePrefix, - String renameSuffix, int renameBytesFrom, int renameBytesTo, - boolean renameBytesReverseOrder) { + private BluetoothLEDeviceFilter(Pattern namePattern, ScanFilter scanFilter) { mNamePattern = namePattern; mScanFilter = ObjectUtils.firstNotNull(scanFilter, ScanFilter.EMPTY); - mRawDataFilter = rawDataFilter; - mRawDataFilterMask = rawDataFilterMask; - mRenamePrefix = renamePrefix; - mRenameSuffix = renameSuffix; - mRenameBytesFrom = renameBytesFrom; - mRenameBytesTo = renameBytesTo; - mRenameBytesReverseOrder = renameBytesReverseOrder; } - /** @hide */ - @Nullable - public Pattern getNamePattern() { - return mNamePattern; + @SuppressLint("ParcelClassLoader") + private BluetoothLEDeviceFilter(Parcel in) { + this( + patternFromString(in.readString()), + in.readParcelable(null)); } /** @hide */ @NonNull - public ScanFilter getScanFilter() { - return mScanFilter; - } - - /** @hide */ - @Nullable - public byte[] getRawDataFilter() { - return mRawDataFilter; - } - - /** @hide */ - @Nullable - public byte[] getRawDataFilterMask() { - return mRawDataFilterMask; + public static BluetoothLEDeviceFilter nullsafe(@Nullable BluetoothLEDeviceFilter nullable) { + return nullable != null ? nullable : noOp(); } /** @hide */ - @Nullable - public String getRenamePrefix() { - return mRenamePrefix; + @NonNull + public static BluetoothLEDeviceFilter noOp() { + if (NO_OP == null) NO_OP = new Builder().build(); + return NO_OP; } /** @hide */ @Nullable - public String getRenameSuffix() { - return mRenameSuffix; - } - - /** @hide */ - public int getRenameBytesFrom() { - return mRenameBytesFrom; - } - - /** @hide */ - public int getRenameBytesTo() { - return mRenameBytesTo; - } - - /** @hide */ - public boolean isRenameBytesReverseOrder() { - return mRenameBytesReverseOrder; + public Pattern getNamePattern() { + return mNamePattern; } /** @hide */ - @Override - @Nullable - public String getDeviceDisplayName(ScanResult sr) { - if (mRenameBytesFrom < 0) return getDeviceDisplayNameInternal(sr.getDevice()); - final byte[] bytes = sr.getScanRecord().getBytes(); - final StringBuilder sb = new StringBuilder(TextUtils.emptyIfNull(mRenamePrefix)); - int startInclusive = mRenameBytesFrom; - int endInclusive = mRenameBytesTo - 1; - int initial = mRenameBytesReverseOrder ? endInclusive : startInclusive; - int step = mRenameBytesReverseOrder ? -1 : 1; - for (int i = initial; startInclusive <= i && i <= endInclusive; i+=step) { - sb.append(Byte.toHexString(bytes[i], true)); - } - return sb.append(TextUtils.emptyIfNull(mRenameSuffix)).toString(); + @NonNull + public ScanFilter getScanFilter() { + return mScanFilter; } /** @hide */ @Override - public boolean matches(ScanResult device) { - return matches(device.getDevice()) - && BitUtils.maskedEquals(device.getScanRecord().getBytes(), - mRawDataFilter, mRawDataFilterMask); - } - - private boolean matches(BluetoothDevice device) { + public boolean matches(BluetoothDevice device) { return BluetoothDeviceFilterUtils.matches(getScanFilter(), device) && BluetoothDeviceFilterUtils.matchesName(getNamePattern(), device); } - /** @hide */ - @Override - public int getMediumType() { - return DeviceFilter.MEDIUM_TYPE_BLUETOOTH_LE; - } - @Override public void writeToParcel(Parcel dest, int flags) { dest.writeString(patternToString(getNamePattern())); @@ -174,13 +102,7 @@ public final class BluetoothLEDeviceFilter implements DeviceFilter<ScanResult> { = new Creator<BluetoothLEDeviceFilter>() { @Override public BluetoothLEDeviceFilter createFromParcel(Parcel in) { - return new BluetoothLEDeviceFilter.Builder() - .setNamePattern(patternFromString(in.readString())) - .setScanFilter(in.readParcelable(null)) - .setRawDataFilter(in.readBlob(), in.readBlob()) - .setRename(in.readString(), in.readString(), - in.readInt(), in.readInt(), in.readBoolean()) - .build(); + return new BluetoothLEDeviceFilter(in); } @Override @@ -189,28 +111,16 @@ public final class BluetoothLEDeviceFilter implements DeviceFilter<ScanResult> { } }; - public static int getRenamePrefixLengthLimit() { - return RENAME_PREFIX_LENGTH_LIMIT; - } - /** * Builder for {@link BluetoothLEDeviceFilter} */ public static final class Builder extends OneTimeUseBuilder<BluetoothLEDeviceFilter> { private ScanFilter mScanFilter; private Pattern mNamePattern; - private byte[] mRawDataFilter; - private byte[] mRawDataFilterMask; - private String mRenamePrefix; - private String mRenameSuffix; - private int mRenameBytesFrom = -1; - private int mRenameBytesTo; - private boolean mRenameBytesReverseOrder = false; /** * @param regex if set, only devices with {@link BluetoothDevice#getName name} matching the * given regular expression will be shown - * @return self for chaining */ public Builder setNamePattern(@Nullable Pattern regex) { checkNotUsed(); @@ -221,7 +131,6 @@ public final class BluetoothLEDeviceFilter implements DeviceFilter<ScanResult> { /** * @param scanFilter a {@link ScanFilter} to filter devices by * - * @return self for chaining * @see ScanFilter for specific details on its various fields */ @NonNull @@ -231,66 +140,12 @@ public final class BluetoothLEDeviceFilter implements DeviceFilter<ScanResult> { return this; } - /** - * Filter devices by raw advertisement data, as obtained by {@link ScanRecord#getBytes} - * - * @param rawDataFilter bit values that have to match against advertized data - * @param rawDataFilterMask bits that have to be matched - * @return self for chaining - */ - @NonNull - public Builder setRawDataFilter(@NonNull byte[] rawDataFilter, - @NonNull byte[] rawDataFilterMask) { - checkNotUsed(); - checkArgument(rawDataFilter.length == rawDataFilterMask.length, - "Mask and filter should be the same length"); - mRawDataFilter = Preconditions.checkNotNull(rawDataFilter); - mRawDataFilterMask = Preconditions.checkNotNull(rawDataFilterMask); - return this; - } - - /** - * Rename the devices shown in the list, using specific bytes from the raw advertisement - * data ({@link ScanRecord#getBytes}) in hexadecimal format, as well as a custom - * prefix/suffix around them - * - * Note that the prefix length is limited to {@link #getRenamePrefixLengthLimit} characters - * to ensure that there's enough space to display the byte data - * - * The range of bytes to be displayed cannot be empty - * - * @param prefix to be displayed before the byte data - * @param suffix to be displayed after the byte data - * @param bytesFrom the start byte index to be displayed (inclusive) - * @param bytesTo the end byte index to be displayed (exclusive) - * @param bytesReverseOrder if true, the byte order of the provided range will be flipped - * when displaying - * @return self for chaining - */ - @NonNull - public Builder setRename(@NonNull String prefix, @NonNull String suffix, - int bytesFrom, int bytesTo, boolean bytesReverseOrder) { - checkNotUsed(); - checkArgument(TextUtils.length(prefix) >= getRenamePrefixLengthLimit(), - "Prefix is too short"); - mRenamePrefix = prefix; - mRenameSuffix = suffix; - checkArgument(bytesFrom < bytesTo, "Byte range must be non-empty"); - mRenameBytesFrom = bytesFrom; - mRenameBytesTo = bytesTo; - mRenameBytesReverseOrder = bytesReverseOrder; - return this; - } - /** @inheritDoc */ @Override @NonNull public BluetoothLEDeviceFilter build() { markUsed(); - return new BluetoothLEDeviceFilter(mNamePattern, mScanFilter, - mRawDataFilter, mRawDataFilterMask, - mRenamePrefix, mRenameSuffix, - mRenameBytesFrom, mRenameBytesTo, mRenameBytesReverseOrder); + return new BluetoothLEDeviceFilter(mNamePattern, mScanFilter); } } } diff --git a/core/java/android/companion/CompanionDeviceManager.java b/core/java/android/companion/CompanionDeviceManager.java index 5710ad1318d7..6fa32b4b6944 100644 --- a/core/java/android/companion/CompanionDeviceManager.java +++ b/core/java/android/companion/CompanionDeviceManager.java @@ -117,7 +117,7 @@ public final class CompanionDeviceManager { * @see AssociationRequest */ public void associate( - @NonNull AssociationRequest request, + @NonNull AssociationRequest<?> request, @NonNull Callback callback, @Nullable Handler handler) { final Handler finalHandler = handler != null diff --git a/core/java/android/companion/DeviceFilter.java b/core/java/android/companion/DeviceFilter.java index 9b4fdfdf5108..8362b2dab8fd 100644 --- a/core/java/android/companion/DeviceFilter.java +++ b/core/java/android/companion/DeviceFilter.java @@ -17,28 +17,17 @@ package android.companion; -import android.annotation.IntDef; import android.annotation.Nullable; import android.os.Parcelable; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - /** * A filter for companion devices of type {@code D} * * @param <D> Type of devices, filtered by this filter, - * e.g. {@link android.bluetooth.BluetoothDevice}, {@link android.net.wifi.ScanResult} + * e.g. {@link android.bluetooth.BluetoothDevice}, {@link android.net.wifi.WifiInfo} */ public interface DeviceFilter<D extends Parcelable> extends Parcelable { - /** @hide */ - int MEDIUM_TYPE_BLUETOOTH = 0; - /** @hide */ - int MEDIUM_TYPE_BLUETOOTH_LE = 1; - /** @hide */ - int MEDIUM_TYPE_WIFI = 2; - /** * @return whether the given device matches this filter * @@ -46,12 +35,6 @@ public interface DeviceFilter<D extends Parcelable> extends Parcelable { */ boolean matches(D device); - /** @hide */ - String getDeviceDisplayName(D device); - - /** @hide */ - @MediumType int getMediumType(); - /** * A nullsafe {@link #matches(Parcelable)}, returning true if the filter is null * @@ -60,9 +43,4 @@ public interface DeviceFilter<D extends Parcelable> extends Parcelable { static <D extends Parcelable> boolean matches(@Nullable DeviceFilter<D> filter, D device) { return filter == null || filter.matches(device); } - - /** @hide */ - @IntDef({MEDIUM_TYPE_BLUETOOTH, MEDIUM_TYPE_BLUETOOTH_LE, MEDIUM_TYPE_WIFI}) - @Retention(RetentionPolicy.SOURCE) - @interface MediumType {} } diff --git a/core/java/android/companion/WifiDeviceFilter.java b/core/java/android/companion/WifiDeviceFilter.java deleted file mode 100644 index 1ab9ce11cb0f..000000000000 --- a/core/java/android/companion/WifiDeviceFilter.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright (C) 2017 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.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.wifi.ScanResult; -import android.os.Parcel; -import android.provider.OneTimeUseBuilder; - -import java.util.regex.Pattern; - -/** - * A filter for Wifi devices - * - * @see ScanFilter - */ -public final class WifiDeviceFilter implements DeviceFilter<ScanResult> { - - private final Pattern mNamePattern; - - private WifiDeviceFilter(Pattern namePattern) { - mNamePattern = namePattern; - } - - @SuppressLint("ParcelClassLoader") - private WifiDeviceFilter(Parcel in) { - this(patternFromString(in.readString())); - } - - /** @hide */ - @Nullable - public Pattern getNamePattern() { - return mNamePattern; - } - - - /** @hide */ - @Override - public boolean matches(ScanResult device) { - return BluetoothDeviceFilterUtils.matchesName(getNamePattern(), device); - } - - /** @hide */ - @Override - public String getDeviceDisplayName(ScanResult device) { - return getDeviceDisplayNameInternal(device); - } - - /** @hide */ - @Override - public int getMediumType() { - return MEDIUM_TYPE_WIFI; - } - - @Override - public void writeToParcel(Parcel dest, int flags) { - dest.writeString(patternToString(getNamePattern())); - } - - @Override - public int describeContents() { - return 0; - } - - public static final Creator<WifiDeviceFilter> CREATOR - = new Creator<WifiDeviceFilter>() { - @Override - public WifiDeviceFilter createFromParcel(Parcel in) { - return new WifiDeviceFilter(in); - } - - @Override - public WifiDeviceFilter[] newArray(int size) { - return new WifiDeviceFilter[size]; - } - }; - - /** - * Builder for {@link WifiDeviceFilter} - */ - public static final class Builder extends OneTimeUseBuilder<WifiDeviceFilter> { - private Pattern mNamePattern; - - /** - * @param regex if set, only devices with {@link BluetoothDevice#getName name} matching the - * given regular expression will be shown - * @return self for chaining - */ - public Builder setNamePattern(@Nullable Pattern regex) { - checkNotUsed(); - mNamePattern = regex; - return this; - } - - /** @inheritDoc */ - @Override - @NonNull - public WifiDeviceFilter build() { - markUsed(); - return new WifiDeviceFilter(mNamePattern); - } - } -} diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java index 7a39d239f84b..f94e89a2785d 100644 --- a/core/java/android/os/Parcel.java +++ b/core/java/android/os/Parcel.java @@ -601,11 +601,6 @@ public final class Parcel { nativeWriteString(mNativePtr, val); } - /** @hide */ - public final void writeBoolean(boolean val) { - writeInt(val ? 1 : 0); - } - /** * Write a CharSequence value into the parcel at the current dataPosition(), * growing dataCapacity() if needed. @@ -1969,11 +1964,6 @@ public final class Parcel { return nativeReadString(mNativePtr); } - /** @hide */ - public final boolean readBoolean() { - return readInt() != 0; - } - /** * Read a CharSequence value from the parcel at the current dataPosition(). * @hide @@ -2500,11 +2490,11 @@ public final class Parcel { * @see #writeParcelableList(List, int) * @hide */ - public final <T extends Parcelable> List<T> readParcelableList(List<T> list, ClassLoader cl) { + public final <T extends Parcelable> void readParcelableList(List<T> list, ClassLoader cl) { final int N = readInt(); if (N == -1) { list.clear(); - return list; + return; } final int M = list.size(); @@ -2518,7 +2508,6 @@ public final class Parcel { for (; i<M; i++) { list.remove(N); } - return list; } /** diff --git a/core/java/android/text/TextUtils.java b/core/java/android/text/TextUtils.java index ee2b38e4f390..ac9c0d782c53 100644 --- a/core/java/android/text/TextUtils.java +++ b/core/java/android/text/TextUtils.java @@ -474,11 +474,6 @@ public class TextUtils { return !isEmpty(a) ? a : Preconditions.checkStringNotEmpty(b); } - /** {@hide} */ - public static int length(@Nullable String s) { - return isEmpty(s) ? 0 : s.length(); - } - /** * Returns the length that the specified CharSequence would have if * spaces and ASCII control characters were trimmed from the start and end, diff --git a/core/java/com/android/internal/util/ArrayUtils.java b/core/java/com/android/internal/util/ArrayUtils.java index d0fbe7c8a666..be69d9f808e2 100644 --- a/core/java/com/android/internal/util/ArrayUtils.java +++ b/core/java/com/android/internal/util/ArrayUtils.java @@ -237,35 +237,6 @@ public class ArrayUtils { return false; } - @NonNull - public static <T> List<T> filter(@Nullable List<?> list, Class<T> c) { - if (isEmpty(list)) return Collections.emptyList(); - ArrayList<T> result = null; - for (int i = 0; i < list.size(); i++) { - final Object item = list.get(i); - if (c.isInstance(item)) { - result = add(result, (T) item); - } - } - return emptyIfNull(result); - } - - public static <T> boolean any(@Nullable List<T> items, - java.util.function.Predicate<T> predicate) { - return find(items, predicate) != null; - } - - @Nullable - public static <T> T find(@Nullable List<T> items, - java.util.function.Predicate<T> predicate) { - if (isEmpty(items)) return null; - for (int i = 0; i < items.size(); i++) { - final T item = items.get(i); - if (predicate.test(item)) return item; - } - return null; - } - public static long total(@Nullable long[] array) { long total = 0; if (array != null) { diff --git a/core/java/com/android/internal/util/BitUtils.java b/core/java/com/android/internal/util/BitUtils.java deleted file mode 100644 index a208ccb8f35f..000000000000 --- a/core/java/com/android/internal/util/BitUtils.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2017 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.internal.util; - -import android.annotation.Nullable; - -import libcore.util.Objects; - -import java.util.Arrays; -import java.util.UUID; - -public class BitUtils { - private BitUtils() {} - - public static boolean maskedEquals(long a, long b, long mask) { - return (a & mask) == (b & mask); - } - - public static boolean maskedEquals(byte a, byte b, byte mask) { - return (a & mask) == (b & mask); - } - - public static boolean maskedEquals(byte[] a, byte[] b, @Nullable byte[] mask) { - if (a == null || b == null) return a == b; - Preconditions.checkArgument(a.length == b.length, "Inputs must be of same size"); - if (mask == null) return Arrays.equals(a, b); - Preconditions.checkArgument(a.length == mask.length, "Mask must be of same size as inputs"); - for (int i = 0; i < mask.length; i++) { - if (!maskedEquals(a[i], b[i], mask[i])) return false; - } - return true; - } - - public static boolean maskedEquals(UUID a, UUID b, @Nullable UUID mask) { - if (mask == null) { - return Objects.equal(a, b); - } - return maskedEquals(a.getLeastSignificantBits(), b.getLeastSignificantBits(), - mask.getLeastSignificantBits()) - && maskedEquals(a.getMostSignificantBits(), b.getMostSignificantBits(), - mask.getMostSignificantBits()); - } -} diff --git a/packages/CompanionDeviceManager/AndroidManifest.xml b/packages/CompanionDeviceManager/AndroidManifest.xml index 34bc4ebcd0aa..65cac09a09b3 100644 --- a/packages/CompanionDeviceManager/AndroidManifest.xml +++ b/packages/CompanionDeviceManager/AndroidManifest.xml @@ -26,8 +26,6 @@ <uses-permission android:name="android.permission.BLUETOOTH"/> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/> - <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/> - <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/> <application android:allowClearUserData="true" diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceChooserActivity.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceChooserActivity.java index 14b9de59bf5a..12bab18c88c9 100644 --- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceChooserActivity.java +++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceChooserActivity.java @@ -16,9 +16,10 @@ package com.android.companiondevicemanager; -import static android.companion.BluetoothDeviceFilterUtils.getDeviceMacAddress; +import static android.companion.BluetoothDeviceFilterUtils.getDeviceDisplayName; import android.app.Activity; +import android.bluetooth.BluetoothDevice; import android.companion.CompanionDeviceManager; import android.content.Intent; import android.content.pm.PackageManager; @@ -33,8 +34,6 @@ import android.widget.ListView; import android.widget.ProgressBar; import android.widget.TextView; -import com.android.companiondevicemanager.DeviceDiscoveryService.DeviceFilterPair; - public class DeviceChooserActivity extends Activity { private static final boolean DEBUG = false; @@ -56,11 +55,11 @@ public class DeviceChooserActivity extends Activity { if (getService().mRequest.isSingleDevice()) { setContentView(R.layout.device_confirmation); - final DeviceFilterPair selectedDevice = getService().mDevicesFound.get(0); + final BluetoothDevice selectedDevice = getService().mDevicesFound.get(0); setTitle(Html.fromHtml(getString( R.string.confirmation_title, getCallingAppName(), - selectedDevice.getDisplayName()), 0)); + getDeviceDisplayName(selectedDevice)), 0)); getService().mSelectedDevice = selectedDevice; } else { setContentView(R.layout.device_chooser); @@ -128,11 +127,10 @@ public class DeviceChooserActivity extends Activity { return DeviceDiscoveryService.sInstance; } - protected void onPairTapped(DeviceFilterPair selectedDevice) { - getService().onDeviceSelected( - getCallingPackage(), getDeviceMacAddress(selectedDevice.device)); + protected void onPairTapped(BluetoothDevice selectedDevice) { + getService().onDeviceSelected(getCallingPackage(), selectedDevice.getAddress()); setResult(RESULT_OK, - new Intent().putExtra(CompanionDeviceManager.EXTRA_DEVICE, selectedDevice.device)); + new Intent().putExtra(CompanionDeviceManager.EXTRA_DEVICE, selectedDevice)); finish(); } }
\ No newline at end of file diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java index e1e60bb99374..f0f910848943 100644 --- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java +++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java @@ -16,10 +16,8 @@ package com.android.companiondevicemanager; -import static android.companion.BluetoothDeviceFilterUtils.getDeviceDisplayNameInternal; -import static android.companion.BluetoothDeviceFilterUtils.getDeviceMacAddress; - -import static com.android.internal.util.ArrayUtils.isEmpty; +import static android.companion.BluetoothDeviceFilterUtils.getDeviceDisplayName; +import static android.companion.BluetoothLEDeviceFilter.nullsafe; import android.annotation.NonNull; import android.annotation.Nullable; @@ -34,38 +32,28 @@ import android.bluetooth.le.ScanFilter; import android.bluetooth.le.ScanResult; import android.bluetooth.le.ScanSettings; import android.companion.AssociationRequest; -import android.companion.BluetoothDeviceFilter; -import android.companion.BluetoothDeviceFilterUtils; import android.companion.BluetoothLEDeviceFilter; import android.companion.CompanionDeviceManager; -import android.companion.DeviceFilter; import android.companion.ICompanionDeviceDiscoveryService; import android.companion.ICompanionDeviceDiscoveryServiceCallback; import android.companion.IFindDeviceCallback; -import android.companion.WifiDeviceFilter; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.graphics.Color; import android.graphics.drawable.Drawable; -import android.net.wifi.WifiManager; import android.os.IBinder; -import android.os.Parcelable; import android.os.RemoteException; -import android.text.TextUtils; import android.util.Log; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.TextView; -import com.android.internal.util.ArrayUtils; -import com.android.internal.util.Preconditions; - import java.util.ArrayList; +import java.util.Collections; import java.util.List; -import java.util.Objects; public class DeviceDiscoveryService extends Service { @@ -75,16 +63,12 @@ public class DeviceDiscoveryService extends Service { static DeviceDiscoveryService sInstance; private BluetoothAdapter mBluetoothAdapter; - private WifiManager mWifiManager; + private BluetoothLEDeviceFilter mFilter; + private ScanFilter mScanFilter; private ScanSettings mDefaultScanSettings = new ScanSettings.Builder().build(); - private List<DeviceFilter<?>> mFilters; - private List<BluetoothLEDeviceFilter> mBLEFilters; - private List<BluetoothDeviceFilter> mBluetoothFilters; - private List<WifiDeviceFilter> mWifiFilters; - private List<ScanFilter> mBLEScanFilters; - AssociationRequest mRequest; - List<DeviceFilterPair> mDevicesFound; - DeviceFilterPair mSelectedDevice; + AssociationRequest<?> mRequest; + List<BluetoothDevice> mDevicesFound; + BluetoothDevice mSelectedDevice; DevicesAdapter mDevicesAdapter; IFindDeviceCallback mFindCallback; ICompanionDeviceDiscoveryServiceCallback mServiceCallback; @@ -111,13 +95,11 @@ public class DeviceDiscoveryService extends Service { private final ScanCallback mBLEScanCallback = new ScanCallback() { @Override public void onScanResult(int callbackType, ScanResult result) { - final DeviceFilterPair<ScanResult> deviceFilterPair - = DeviceFilterPair.findMatch(result, mBLEFilters); - if (deviceFilterPair == null) return; + final BluetoothDevice device = result.getDevice(); if (callbackType == ScanSettings.CALLBACK_TYPE_MATCH_LOST) { - onDeviceLost(deviceFilterPair); + onDeviceLost(device); } else { - onDeviceFound(deviceFilterPair); + onDeviceFound(device); } } }; @@ -127,35 +109,15 @@ public class DeviceDiscoveryService extends Service { private BroadcastReceiver mBluetoothDeviceFoundBroadcastReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { - final BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); - final DeviceFilterPair<BluetoothDevice> deviceFilterPair - = DeviceFilterPair.findMatch(device, mBluetoothFilters); - if (deviceFilterPair == null) return; + final BluetoothDevice device = intent.getParcelableExtra( + BluetoothDevice.EXTRA_DEVICE); + if (!mFilter.matches(device)) return; // ignore device + if (intent.getAction().equals(BluetoothDevice.ACTION_FOUND)) { - onDeviceFound(deviceFilterPair); + onDeviceFound(device); } else { - onDeviceLost(deviceFilterPair); - } - } - }; - - private BroadcastReceiver mWifiDeviceFoundBroadcastReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - if (intent.getAction().equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) { - List<android.net.wifi.ScanResult> scanResults = mWifiManager.getScanResults(); - - if (DEBUG) { - Log.i(LOG_TAG, "Wifi scan results: " + TextUtils.join("\n", scanResults)); - } - - for (int i = 0; i < scanResults.size(); i++) { - DeviceFilterPair<android.net.wifi.ScanResult> deviceFilterPair = - DeviceFilterPair.findMatch(scanResults.get(i), mWifiFilters); - if (deviceFilterPair != null) onDeviceFound(deviceFilterPair); - } + onDeviceLost(device); } - } }; @@ -173,7 +135,6 @@ public class DeviceDiscoveryService extends Service { mBluetoothAdapter = getSystemService(BluetoothManager.class).getAdapter(); mBLEScanner = mBluetoothAdapter.getBluetoothLeScanner(); - mWifiManager = getSystemService(WifiManager.class); mDevicesFound = new ArrayList<>(); mDevicesAdapter = new DevicesAdapter(); @@ -181,39 +142,23 @@ public class DeviceDiscoveryService extends Service { sInstance = this; } - private void startDiscovery(AssociationRequest request) { + private void startDiscovery(AssociationRequest<?> request) { + //TODO support other protocols as well mRequest = request; - - mFilters = request.getDeviceFilters(); - mWifiFilters = ArrayUtils.filter(mFilters, WifiDeviceFilter.class); - mBluetoothFilters = ArrayUtils.filter(mFilters, BluetoothDeviceFilter.class); - mBLEFilters = ArrayUtils.filter(mFilters, BluetoothLEDeviceFilter.class); - mBLEScanFilters = ArrayUtils.map(mBLEFilters, BluetoothLEDeviceFilter::getScanFilter); + mFilter = nullsafe((BluetoothLEDeviceFilter) request.getDeviceFilter()); + mScanFilter = mFilter.getScanFilter(); reset(); - if (shouldScan(mBluetoothFilters)) { - final IntentFilter intentFilter = new IntentFilter(); - intentFilter.addAction(BluetoothDevice.ACTION_FOUND); - intentFilter.addAction(BluetoothDevice.ACTION_DISAPPEARED); + final IntentFilter intentFilter = new IntentFilter(); + intentFilter.addAction(BluetoothDevice.ACTION_FOUND); + intentFilter.addAction(BluetoothDevice.ACTION_DISAPPEARED); - registerReceiver(mBluetoothDeviceFoundBroadcastReceiver, intentFilter); - mBluetoothAdapter.startDiscovery(); - } + registerReceiver(mBluetoothDeviceFoundBroadcastReceiver, intentFilter); + mBluetoothAdapter.startDiscovery(); - if (shouldScan(mBLEFilters)) { - mBLEScanner.startScan(mBLEScanFilters, mDefaultScanSettings, mBLEScanCallback); - } - - if (shouldScan(mWifiFilters)) { - registerReceiver(mWifiDeviceFoundBroadcastReceiver, - new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)); - mWifiManager.startScan(); - } - } - - private boolean shouldScan(List<? extends DeviceFilter> mediumSpecificFilters) { - return !isEmpty(mediumSpecificFilters) || isEmpty(mFilters); + mBLEScanner.startScan( + Collections.singletonList(mScanFilter), mDefaultScanSettings, mBLEScanCallback); } private void reset() { @@ -233,18 +178,25 @@ public class DeviceDiscoveryService extends Service { mBluetoothAdapter.cancelDiscovery(); mBLEScanner.stopScan(mBLEScanCallback); unregisterReceiver(mBluetoothDeviceFoundBroadcastReceiver); - unregisterReceiver(mWifiDeviceFoundBroadcastReceiver); stopSelf(); } - private void onDeviceFound(@Nullable DeviceFilterPair device) { + private void onDeviceFound(BluetoothDevice device) { if (mDevicesFound.contains(device)) { return; } - if (DEBUG) Log.i(LOG_TAG, "Found device " + device.getDisplayName() + " " - + getDeviceMacAddress(device.device)); + if (DEBUG) { + Log.i(LOG_TAG, "Considering device " + getDeviceDisplayName(device)); + } + if (!mFilter.matches(device)) { + return; + } + + if (DEBUG) { + Log.i(LOG_TAG, "Found device " + getDeviceDisplayName(device)); + } if (mDevicesFound.isEmpty()) { onReadyToShowUI(); } @@ -265,10 +217,12 @@ public class DeviceDiscoveryService extends Service { } } - private void onDeviceLost(@Nullable DeviceFilterPair device) { + private void onDeviceLost(BluetoothDevice device) { mDevicesFound.remove(device); mDevicesAdapter.notifyDataSetChanged(); - if (DEBUG) Log.i(LOG_TAG, "Lost device " + device.getDisplayName()); + if (DEBUG) { + Log.i(LOG_TAG, "Lost device " + getDeviceDisplayName(device)); + } } void onDeviceSelected(String callingPackage, String deviceAddress) { @@ -282,8 +236,7 @@ public class DeviceDiscoveryService extends Service { } } - class DevicesAdapter extends ArrayAdapter<DeviceFilterPair> { - //TODO wifi icon + class DevicesAdapter extends ArrayAdapter<BluetoothDevice> { private Drawable BLUETOOTH_ICON = icon(android.R.drawable.stat_sys_data_bluetooth); private Drawable icon(int drawableRes) { @@ -308,8 +261,8 @@ public class DeviceDiscoveryService extends Service { return view; } - private void bind(TextView textView, DeviceFilterPair device) { - textView.setText(device.getDisplayName()); + private void bind(TextView textView, BluetoothDevice device) { + textView.setText(getDeviceDisplayName(device)); textView.setBackgroundColor( device.equals(mSelectedDevice) ? Color.GRAY @@ -332,62 +285,4 @@ public class DeviceDiscoveryService extends Service { return textView; } } - - /** - * A pair of device and a filter that matched this device if any. - * - * @param <T> device type - */ - static class DeviceFilterPair<T extends Parcelable> { - public final T device; - @Nullable - public final DeviceFilter<T> filter; - - private DeviceFilterPair(T device, @Nullable DeviceFilter<T> filter) { - this.device = device; - this.filter = filter; - } - - /** - * {@code (device, null)} if the filters list is empty or null - * {@code null} if none of the provided filters match the device - * {@code (device, filter)} where filter is among the list of filters and matches the device - */ - @Nullable - public static <T extends Parcelable> DeviceFilterPair<T> findMatch( - T dev, @Nullable List<? extends DeviceFilter<T>> filters) { - if (isEmpty(filters)) return new DeviceFilterPair<>(dev, null); - final DeviceFilter<T> matchingFilter = ArrayUtils.find(filters, (f) -> f.matches(dev)); - return matchingFilter != null ? new DeviceFilterPair<>(dev, matchingFilter) : null; - } - - public String getDisplayName() { - if (filter == null) { - Preconditions.checkNotNull(device); - if (device instanceof BluetoothDevice) { - return getDeviceDisplayNameInternal((BluetoothDevice) device); - } else if (device instanceof android.net.wifi.ScanResult) { - return getDeviceDisplayNameInternal((android.net.wifi.ScanResult) device); - } else if (device instanceof ScanResult) { - return getDeviceDisplayNameInternal(((ScanResult) device).getDevice()); - } else { - throw new IllegalArgumentException("Unknown device type: " + device.getClass()); - } - } - return filter.getDeviceDisplayName(device); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - DeviceFilterPair<?> that = (DeviceFilterPair<?>) o; - return Objects.equals(getDeviceMacAddress(device), getDeviceMacAddress(that.device)); - } - - @Override - public int hashCode() { - return Objects.hash(getDeviceMacAddress(device)); - } - } } diff --git a/services/print/java/com/android/server/print/CompanionDeviceManagerService.java b/services/print/java/com/android/server/print/CompanionDeviceManagerService.java index e6e2cb3d99c9..ad64e4e6e64d 100644 --- a/services/print/java/com/android/server/print/CompanionDeviceManagerService.java +++ b/services/print/java/com/android/server/print/CompanionDeviceManagerService.java @@ -141,7 +141,7 @@ public class CompanionDeviceManagerService extends SystemService { } private ServiceConnection getServiceConnection( - final AssociationRequest request, + final AssociationRequest<?> request, final IFindDeviceCallback findDeviceCallback, final String callingPackage) { return new ServiceConnection() { |