diff --git a/nearby/framework/Android.bp b/nearby/framework/Android.bp
index 278f8231257e48fed191e8734e0ce2e98e5060da..f32929596d0bc84ce10e3c3ef57264c4ff37ff0a 100644
--- a/nearby/framework/Android.bp
+++ b/nearby/framework/Android.bp
@@ -52,5 +52,7 @@ java_library {
static_libs: [
"modules-utils-preconditions",
],
- visibility: ["//packages/modules/Connectivity/nearby/tests:__subpackages__"],
+ visibility: [
+ "//packages/modules/Connectivity/nearby/tests:__subpackages__",
+ ],
}
diff --git a/nearby/framework/java/android/nearby/FastPairAccountKeyDeviceMetadata.java b/nearby/framework/java/android/nearby/FastPairAccountKeyDeviceMetadata.java
deleted file mode 100644
index d42fbf4054104ed10e0efbbeea9479fb7b0ef53c..0000000000000000000000000000000000000000
--- a/nearby/framework/java/android/nearby/FastPairAccountKeyDeviceMetadata.java
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.nearby;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.nearby.aidl.FastPairAccountKeyDeviceMetadataParcel;
-
-/**
- * Class for metadata of a Fast Pair device associated with an account.
- *
- * @hide
- */
-public class FastPairAccountKeyDeviceMetadata {
-
- FastPairAccountKeyDeviceMetadataParcel mMetadataParcel;
-
- FastPairAccountKeyDeviceMetadata(FastPairAccountKeyDeviceMetadataParcel metadataParcel) {
- this.mMetadataParcel = metadataParcel;
- }
-
- /**
- * Get Device Account Key, which uniquely identifies a Fast Pair device associated with an
- * account. AccountKey is 16 bytes: first byte is 0x04. Other 15 bytes are randomly generated.
- *
- * @return 16-byte Account Key.
- * @hide
- */
- @Nullable
- public byte[] getDeviceAccountKey() {
- return mMetadataParcel.deviceAccountKey;
- }
-
- /**
- * Get a hash value of device's account key and public bluetooth address without revealing the
- * public bluetooth address. Sha256 hash value is 32 bytes.
- *
- * @return 32-byte Sha256 hash value.
- * @hide
- */
- @Nullable
- public byte[] getSha256DeviceAccountKeyPublicAddress() {
- return mMetadataParcel.sha256DeviceAccountKeyPublicAddress;
- }
-
- /**
- * Get metadata of a Fast Pair device type.
- *
- * @hide
- */
- @Nullable
- public FastPairDeviceMetadata getFastPairDeviceMetadata() {
- if (mMetadataParcel.metadata == null) {
- return null;
- }
- return new FastPairDeviceMetadata(mMetadataParcel.metadata);
- }
-
- /**
- * Get Fast Pair discovery item, which is tied to both the device type and the account.
- *
- * @hide
- */
- @Nullable
- public FastPairDiscoveryItem getFastPairDiscoveryItem() {
- if (mMetadataParcel.discoveryItem == null) {
- return null;
- }
- return new FastPairDiscoveryItem(mMetadataParcel.discoveryItem);
- }
-
- /**
- * Builder used to create FastPairAccountKeyDeviceMetadata.
- *
- * @hide
- */
- public static final class Builder {
-
- private final FastPairAccountKeyDeviceMetadataParcel mBuilderParcel;
-
- /**
- * Default constructor of Builder.
- *
- * @hide
- */
- public Builder() {
- mBuilderParcel = new FastPairAccountKeyDeviceMetadataParcel();
- mBuilderParcel.deviceAccountKey = null;
- mBuilderParcel.sha256DeviceAccountKeyPublicAddress = null;
- mBuilderParcel.metadata = null;
- mBuilderParcel.discoveryItem = null;
- }
-
- /**
- * Set Account Key.
- *
- * @param deviceAccountKey Fast Pair device account key, which is 16 bytes: first byte is
- * 0x04. Next 15 bytes are randomly generated.
- * @return The builder, to facilitate chaining {@code builder.setXXX(..).setXXX(..)}.
- * @hide
- */
- @NonNull
- public Builder setDeviceAccountKey(@Nullable byte[] deviceAccountKey) {
- mBuilderParcel.deviceAccountKey = deviceAccountKey;
- return this;
- }
-
- /**
- * Set sha256 hash value of account key and public bluetooth address.
- *
- * @param sha256DeviceAccountKeyPublicAddress 32-byte sha256 hash value of account key and
- * public bluetooth address.
- * @return The builder, to facilitate chaining {@code builder.setXXX(..).setXXX(..)}.
- * @hide
- */
- @NonNull
- public Builder setSha256DeviceAccountKeyPublicAddress(
- @Nullable byte[] sha256DeviceAccountKeyPublicAddress) {
- mBuilderParcel.sha256DeviceAccountKeyPublicAddress =
- sha256DeviceAccountKeyPublicAddress;
- return this;
- }
-
-
- /**
- * Set Fast Pair metadata.
- *
- * @param metadata Fast Pair metadata.
- * @return The builder, to facilitate chaining {@code builder.setXXX(..).setXXX(..)}.
- * @hide
- */
- @NonNull
- public Builder setFastPairDeviceMetadata(@Nullable FastPairDeviceMetadata metadata) {
- if (metadata == null) {
- mBuilderParcel.metadata = null;
- } else {
- mBuilderParcel.metadata = metadata.mMetadataParcel;
- }
- return this;
- }
-
- /**
- * Set Fast Pair discovery item.
- *
- * @param discoveryItem Fast Pair discovery item.
- * @return The builder, to facilitate chaining {@code builder.setXXX(..).setXXX(..)}.
- * @hide
- */
- @NonNull
- public Builder setFastPairDiscoveryItem(@Nullable FastPairDiscoveryItem discoveryItem) {
- if (discoveryItem == null) {
- mBuilderParcel.discoveryItem = null;
- } else {
- mBuilderParcel.discoveryItem = discoveryItem.mMetadataParcel;
- }
- return this;
- }
-
- /**
- * Build {@link FastPairAccountKeyDeviceMetadata} with the currently set configuration.
- *
- * @hide
- */
- @NonNull
- public FastPairAccountKeyDeviceMetadata build() {
- return new FastPairAccountKeyDeviceMetadata(mBuilderParcel);
- }
- }
-}
diff --git a/nearby/framework/java/android/nearby/FastPairAntispoofKeyDeviceMetadata.java b/nearby/framework/java/android/nearby/FastPairAntispoofKeyDeviceMetadata.java
deleted file mode 100644
index 74831d5183e5c8c945eede014cdf382dbd230055..0000000000000000000000000000000000000000
--- a/nearby/framework/java/android/nearby/FastPairAntispoofKeyDeviceMetadata.java
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.nearby;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.nearby.aidl.FastPairAntispoofKeyDeviceMetadataParcel;
-
-/**
- * Class for a type of registered Fast Pair device keyed by modelID, or antispoofKey.
- *
- * @hide
- */
-public class FastPairAntispoofKeyDeviceMetadata {
-
- FastPairAntispoofKeyDeviceMetadataParcel mMetadataParcel;
- FastPairAntispoofKeyDeviceMetadata(
- FastPairAntispoofKeyDeviceMetadataParcel metadataParcel) {
- this.mMetadataParcel = metadataParcel;
- }
-
- /**
- * Get Antispoof public key.
- *
- * @hide
- */
- @Nullable
- public byte[] getAntispoofPublicKey() {
- return this.mMetadataParcel.antispoofPublicKey;
- }
-
- /**
- * Get metadata of a Fast Pair device type.
- *
- * @hide
- */
- @Nullable
- public FastPairDeviceMetadata getFastPairDeviceMetadata() {
- if (this.mMetadataParcel.deviceMetadata == null) {
- return null;
- }
- return new FastPairDeviceMetadata(this.mMetadataParcel.deviceMetadata);
- }
-
- /**
- * Builder used to create FastPairAntispoofkeyDeviceMetadata.
- *
- * @hide
- */
- public static final class Builder {
-
- private final FastPairAntispoofKeyDeviceMetadataParcel mBuilderParcel;
-
- /**
- * Default constructor of Builder.
- *
- * @hide
- */
- public Builder() {
- mBuilderParcel = new FastPairAntispoofKeyDeviceMetadataParcel();
- mBuilderParcel.antispoofPublicKey = null;
- mBuilderParcel.deviceMetadata = null;
- }
-
- /**
- * Set AntiSpoof public key, which uniquely identify a Fast Pair device type.
- *
- * @param antispoofPublicKey is 64 bytes, see Data Format.
- * @return The builder, to facilitate chaining {@code builder.setXXX(..).setXXX(..)}.
- * @hide
- */
- @NonNull
- public Builder setAntispoofPublicKey(@Nullable byte[] antispoofPublicKey) {
- mBuilderParcel.antispoofPublicKey = antispoofPublicKey;
- return this;
- }
-
- /**
- * Set Fast Pair metadata, which is the property of a Fast Pair device type, including
- * device images and strings.
- *
- * @param metadata Fast Pair device meta data.
- * @return The builder, to facilitate chaining {@code builder.setXXX(..).setXXX(..)}.
- * @hide
- */
- @NonNull
- public Builder setFastPairDeviceMetadata(@Nullable FastPairDeviceMetadata metadata) {
- if (metadata != null) {
- mBuilderParcel.deviceMetadata = metadata.mMetadataParcel;
- } else {
- mBuilderParcel.deviceMetadata = null;
- }
- return this;
- }
-
- /**
- * Build {@link FastPairAntispoofKeyDeviceMetadata} with the currently set configuration.
- *
- * @hide
- */
- @NonNull
- public FastPairAntispoofKeyDeviceMetadata build() {
- return new FastPairAntispoofKeyDeviceMetadata(mBuilderParcel);
- }
- }
-}
diff --git a/nearby/framework/java/android/nearby/FastPairDataProviderService.java b/nearby/framework/java/android/nearby/FastPairDataProviderService.java
deleted file mode 100644
index f1d507471fbab0a37699ff8f90f5e70cdc93f416..0000000000000000000000000000000000000000
--- a/nearby/framework/java/android/nearby/FastPairDataProviderService.java
+++ /dev/null
@@ -1,714 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.nearby;
-
-import android.accounts.Account;
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.app.Service;
-import android.content.Intent;
-import android.nearby.aidl.ByteArrayParcel;
-import android.nearby.aidl.FastPairAccountDevicesMetadataRequestParcel;
-import android.nearby.aidl.FastPairAccountKeyDeviceMetadataParcel;
-import android.nearby.aidl.FastPairAntispoofKeyDeviceMetadataRequestParcel;
-import android.nearby.aidl.FastPairEligibleAccountParcel;
-import android.nearby.aidl.FastPairEligibleAccountsRequestParcel;
-import android.nearby.aidl.FastPairManageAccountDeviceRequestParcel;
-import android.nearby.aidl.FastPairManageAccountRequestParcel;
-import android.nearby.aidl.IFastPairAccountDevicesMetadataCallback;
-import android.nearby.aidl.IFastPairAntispoofKeyDeviceMetadataCallback;
-import android.nearby.aidl.IFastPairDataProvider;
-import android.nearby.aidl.IFastPairEligibleAccountsCallback;
-import android.nearby.aidl.IFastPairManageAccountCallback;
-import android.nearby.aidl.IFastPairManageAccountDeviceCallback;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.util.Log;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
-/**
- * A service class for fast pair data providers outside the system server.
- *
- * Fast pair providers should be wrapped in a non-exported service which returns the result of
- * {@link #getBinder()} from the service's {@link android.app.Service#onBind(Intent)} method. The
- * service should not be exported so that components other than the system server cannot bind to it.
- * Alternatively, the service may be guarded by a permission that only system server can obtain.
- *
- *
Fast Pair providers are identified by their UID / package name.
- *
- * @hide
- */
-public abstract class FastPairDataProviderService extends Service {
- /**
- * The action the wrapping service should have in its intent filter to implement the
- * {@link android.nearby.FastPairDataProviderBase}.
- *
- * @hide
- */
- public static final String ACTION_FAST_PAIR_DATA_PROVIDER =
- "android.nearby.action.FAST_PAIR_DATA_PROVIDER";
-
- /**
- * Manage request type to add, or opt-in.
- *
- * @hide
- */
- public static final int MANAGE_REQUEST_ADD = 0;
-
- /**
- * Manage request type to remove, or opt-out.
- *
- * @hide
- */
- public static final int MANAGE_REQUEST_REMOVE = 1;
-
- /**
- * @hide
- */
- @Retention(RetentionPolicy.SOURCE)
- @IntDef(value = {
- MANAGE_REQUEST_ADD,
- MANAGE_REQUEST_REMOVE})
- @interface ManageRequestType {}
-
- /**
- * Error code for bad request.
- *
- * @hide
- */
- public static final int ERROR_CODE_BAD_REQUEST = 0;
-
- /**
- * Error code for internal error.
- *
- * @hide
- */
- public static final int ERROR_CODE_INTERNAL_ERROR = 1;
-
- /**
- * @hide
- */
- @Retention(RetentionPolicy.SOURCE)
- @IntDef(value = {
- ERROR_CODE_BAD_REQUEST,
- ERROR_CODE_INTERNAL_ERROR})
- @interface ErrorCode {}
-
- private final IBinder mBinder;
- private final String mTag;
-
- /**
- * Constructor of FastPairDataProviderService.
- *
- * @param tag TAG for on device logging.
- * @hide
- */
- public FastPairDataProviderService(@NonNull String tag) {
- mBinder = new Service();
- mTag = tag;
- }
-
- @Override
- @NonNull
- public final IBinder onBind(@NonNull Intent intent) {
- return mBinder;
- }
-
- /**
- * Callback to be invoked when an AntispoofKeyed device metadata is loaded.
- *
- * @hide
- */
- public interface FastPairAntispoofKeyDeviceMetadataCallback {
-
- /**
- * Invoked once the meta data is loaded.
- *
- * @hide
- */
- void onFastPairAntispoofKeyDeviceMetadataReceived(
- @NonNull FastPairAntispoofKeyDeviceMetadata metadata);
-
- /** Invoked in case of error.
- *
- * @hide
- */
- void onError(@ErrorCode int code, @Nullable String message);
- }
-
- /**
- * Callback to be invoked when Fast Pair devices of a given account is loaded.
- *
- * @hide
- */
- public interface FastPairAccountDevicesMetadataCallback {
-
- /**
- * Should be invoked once the metadatas are loaded.
- *
- * @hide
- */
- void onFastPairAccountDevicesMetadataReceived(
- @NonNull Collection metadatas);
- /**
- * Invoked in case of error.
- *
- * @hide
- */
- void onError(@ErrorCode int code, @Nullable String message);
- }
-
- /**
- * Callback to be invoked when FastPair eligible accounts are loaded.
- *
- * @hide
- */
- public interface FastPairEligibleAccountsCallback {
-
- /**
- * Should be invoked once the eligible accounts are loaded.
- *
- * @hide
- */
- void onFastPairEligibleAccountsReceived(
- @NonNull Collection accounts);
- /**
- * Invoked in case of error.
- *
- * @hide
- */
- void onError(@ErrorCode int code, @Nullable String message);
- }
-
- /**
- * Callback to be invoked when a management action is finished.
- *
- * @hide
- */
- public interface FastPairManageActionCallback {
-
- /**
- * Should be invoked once the manage action is successful.
- *
- * @hide
- */
- void onSuccess();
- /**
- * Invoked in case of error.
- *
- * @hide
- */
- void onError(@ErrorCode int code, @Nullable String message);
- }
-
- /**
- * Fulfills the Fast Pair device metadata request by using callback to send back the
- * device meta data of a given modelId.
- *
- * @hide
- */
- public abstract void onLoadFastPairAntispoofKeyDeviceMetadata(
- @NonNull FastPairAntispoofKeyDeviceMetadataRequest request,
- @NonNull FastPairAntispoofKeyDeviceMetadataCallback callback);
-
- /**
- * Fulfills the account tied Fast Pair devices metadata request by using callback to send back
- * all Fast Pair device's metadata of a given account.
- *
- * @hide
- */
- public abstract void onLoadFastPairAccountDevicesMetadata(
- @NonNull FastPairAccountDevicesMetadataRequest request,
- @NonNull FastPairAccountDevicesMetadataCallback callback);
-
- /**
- * Fulfills the Fast Pair eligible accounts request by using callback to send back Fast Pair
- * eligible accounts.
- *
- * @hide
- */
- public abstract void onLoadFastPairEligibleAccounts(
- @NonNull FastPairEligibleAccountsRequest request,
- @NonNull FastPairEligibleAccountsCallback callback);
-
- /**
- * Fulfills the Fast Pair account management request by using callback to send back result.
- *
- * @hide
- */
- public abstract void onManageFastPairAccount(
- @NonNull FastPairManageAccountRequest request,
- @NonNull FastPairManageActionCallback callback);
-
- /**
- * Fulfills the request to manage device-account mapping by using callback to send back result.
- *
- * @hide
- */
- public abstract void onManageFastPairAccountDevice(
- @NonNull FastPairManageAccountDeviceRequest request,
- @NonNull FastPairManageActionCallback callback);
-
- /**
- * Class for reading FastPairAntispoofKeyDeviceMetadataRequest, which specifies the model ID of
- * a Fast Pair device. To fulfill this request, corresponding
- * {@link FastPairAntispoofKeyDeviceMetadata} should be fetched and returned.
- *
- * @hide
- */
- public static class FastPairAntispoofKeyDeviceMetadataRequest {
-
- private final FastPairAntispoofKeyDeviceMetadataRequestParcel mMetadataRequestParcel;
-
- private FastPairAntispoofKeyDeviceMetadataRequest(
- final FastPairAntispoofKeyDeviceMetadataRequestParcel metaDataRequestParcel) {
- this.mMetadataRequestParcel = metaDataRequestParcel;
- }
-
- /**
- * Get modelId (24 bit), the key for FastPairAntispoofKeyDeviceMetadata in the same format
- * returned by Google at device registration time.
- *
- * ModelId format is defined at device registration time, see
- * Model ID.
- * @return raw bytes of modelId in the same format returned by Google at device registration
- * time.
- * @hide
- */
- public @NonNull byte[] getModelId() {
- return this.mMetadataRequestParcel.modelId;
- }
- }
-
- /**
- * Class for reading FastPairAccountDevicesMetadataRequest, which specifies the Fast Pair
- * account and the allow list of the FastPair device keys saved to the account (i.e., FastPair
- * accountKeys).
- *
- * A Fast Pair accountKey is created when a Fast Pair device is saved to an account. It is per
- * Fast Pair device per account.
- *
- * To retrieve all Fast Pair accountKeys saved to an account, the caller needs to set
- * account with an empty allow list.
- *
- * To retrieve metadata of a selected list of Fast Pair devices saved to an account, the caller
- * needs to set account with a non-empty allow list.
- * @hide
- */
- public static class FastPairAccountDevicesMetadataRequest {
-
- private final FastPairAccountDevicesMetadataRequestParcel mMetadataRequestParcel;
-
- private FastPairAccountDevicesMetadataRequest(
- final FastPairAccountDevicesMetadataRequestParcel metaDataRequestParcel) {
- this.mMetadataRequestParcel = metaDataRequestParcel;
- }
-
- /**
- * Get FastPair account, whose Fast Pair devices' metadata is requested.
- *
- * @return a FastPair account.
- * @hide
- */
- public @NonNull Account getAccount() {
- return this.mMetadataRequestParcel.account;
- }
-
- /**
- * Get allowlist of Fast Pair devices using a collection of deviceAccountKeys.
- * Note that as a special case, empty list actually means all FastPair devices under the
- * account instead of none.
- *
- * DeviceAccountKey is 16 bytes: first byte is 0x04. Other 15 bytes are randomly generated.
- *
- * @return allowlist of Fast Pair devices using a collection of deviceAccountKeys.
- * @hide
- */
- public @NonNull Collection getDeviceAccountKeys() {
- if (this.mMetadataRequestParcel.deviceAccountKeys == null) {
- return new ArrayList(0);
- }
- List deviceAccountKeys =
- new ArrayList<>(this.mMetadataRequestParcel.deviceAccountKeys.length);
- for (ByteArrayParcel deviceAccountKey : this.mMetadataRequestParcel.deviceAccountKeys) {
- deviceAccountKeys.add(deviceAccountKey.byteArray);
- }
- return deviceAccountKeys;
- }
- }
-
- /**
- * Class for reading FastPairEligibleAccountsRequest. Upon receiving this request, Fast Pair
- * eligible accounts should be returned to bind Fast Pair devices.
- *
- * @hide
- */
- public static class FastPairEligibleAccountsRequest {
- @SuppressWarnings("UnusedVariable")
- private final FastPairEligibleAccountsRequestParcel mAccountsRequestParcel;
-
- private FastPairEligibleAccountsRequest(
- final FastPairEligibleAccountsRequestParcel accountsRequestParcel) {
- this.mAccountsRequestParcel = accountsRequestParcel;
- }
- }
-
- /**
- * Class for reading FastPairManageAccountRequest. If the request type is MANAGE_REQUEST_ADD,
- * the account is enabled to bind Fast Pair devices; If the request type is
- * MANAGE_REQUEST_REMOVE, the account is disabled to bind more Fast Pair devices. Furthermore,
- * all existing bounded Fast Pair devices are unbounded.
- *
- * @hide
- */
- public static class FastPairManageAccountRequest {
-
- private final FastPairManageAccountRequestParcel mAccountRequestParcel;
-
- private FastPairManageAccountRequest(
- final FastPairManageAccountRequestParcel accountRequestParcel) {
- this.mAccountRequestParcel = accountRequestParcel;
- }
-
- /**
- * Get request type: MANAGE_REQUEST_ADD, or MANAGE_REQUEST_REMOVE.
- *
- * @hide
- */
- public @ManageRequestType int getRequestType() {
- return this.mAccountRequestParcel.requestType;
- }
- /**
- * Get account.
- *
- * @hide
- */
- public @NonNull Account getAccount() {
- return this.mAccountRequestParcel.account;
- }
- }
-
- /**
- * Class for reading FastPairManageAccountDeviceRequest. If the request type is
- * MANAGE_REQUEST_ADD, then a Fast Pair device is bounded to a Fast Pair account. If the
- * request type is MANAGE_REQUEST_REMOVE, then a Fast Pair device is removed from a Fast Pair
- * account.
- *
- * @hide
- */
- public static class FastPairManageAccountDeviceRequest {
-
- private final FastPairManageAccountDeviceRequestParcel mRequestParcel;
-
- private FastPairManageAccountDeviceRequest(
- final FastPairManageAccountDeviceRequestParcel requestParcel) {
- this.mRequestParcel = requestParcel;
- }
-
- /**
- * Get request type: MANAGE_REQUEST_ADD, or MANAGE_REQUEST_REMOVE.
- *
- * @hide
- */
- public @ManageRequestType int getRequestType() {
- return this.mRequestParcel.requestType;
- }
- /**
- * Get account.
- *
- * @hide
- */
- public @NonNull Account getAccount() {
- return this.mRequestParcel.account;
- }
- /**
- * Get account key device metadata.
- *
- * @hide
- */
- public @NonNull FastPairAccountKeyDeviceMetadata getAccountKeyDeviceMetadata() {
- return new FastPairAccountKeyDeviceMetadata(
- this.mRequestParcel.accountKeyDeviceMetadata);
- }
- }
-
- /**
- * Callback class that sends back FastPairAntispoofKeyDeviceMetadata.
- */
- private final class WrapperFastPairAntispoofKeyDeviceMetadataCallback implements
- FastPairAntispoofKeyDeviceMetadataCallback {
-
- private IFastPairAntispoofKeyDeviceMetadataCallback mCallback;
-
- private WrapperFastPairAntispoofKeyDeviceMetadataCallback(
- IFastPairAntispoofKeyDeviceMetadataCallback callback) {
- mCallback = callback;
- }
-
- /**
- * Sends back FastPairAntispoofKeyDeviceMetadata.
- */
- @Override
- public void onFastPairAntispoofKeyDeviceMetadataReceived(
- @NonNull FastPairAntispoofKeyDeviceMetadata metadata) {
- try {
- mCallback.onFastPairAntispoofKeyDeviceMetadataReceived(metadata.mMetadataParcel);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- } catch (RuntimeException e) {
- Log.w(mTag, e);
- }
- }
-
- @Override
- public void onError(@ErrorCode int code, @Nullable String message) {
- try {
- mCallback.onError(code, message);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- } catch (RuntimeException e) {
- Log.w(mTag, e);
- }
- }
- }
-
- /**
- * Callback class that sends back collection of FastPairAccountKeyDeviceMetadata.
- */
- private final class WrapperFastPairAccountDevicesMetadataCallback implements
- FastPairAccountDevicesMetadataCallback {
-
- private IFastPairAccountDevicesMetadataCallback mCallback;
-
- private WrapperFastPairAccountDevicesMetadataCallback(
- IFastPairAccountDevicesMetadataCallback callback) {
- mCallback = callback;
- }
-
- /**
- * Sends back collection of FastPairAccountKeyDeviceMetadata.
- */
- @Override
- public void onFastPairAccountDevicesMetadataReceived(
- @NonNull Collection metadatas) {
- FastPairAccountKeyDeviceMetadataParcel[] metadataParcels =
- new FastPairAccountKeyDeviceMetadataParcel[metadatas.size()];
- int i = 0;
- for (FastPairAccountKeyDeviceMetadata metadata : metadatas) {
- metadataParcels[i] = metadata.mMetadataParcel;
- i = i + 1;
- }
- try {
- mCallback.onFastPairAccountDevicesMetadataReceived(metadataParcels);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- } catch (RuntimeException e) {
- Log.w(mTag, e);
- }
- }
-
- @Override
- public void onError(@ErrorCode int code, @Nullable String message) {
- try {
- mCallback.onError(code, message);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- } catch (RuntimeException e) {
- Log.w(mTag, e);
- }
- }
- }
-
- /**
- * Callback class that sends back eligible Fast Pair accounts.
- */
- private final class WrapperFastPairEligibleAccountsCallback implements
- FastPairEligibleAccountsCallback {
-
- private IFastPairEligibleAccountsCallback mCallback;
-
- private WrapperFastPairEligibleAccountsCallback(
- IFastPairEligibleAccountsCallback callback) {
- mCallback = callback;
- }
-
- /**
- * Sends back the eligible Fast Pair accounts.
- */
- @Override
- public void onFastPairEligibleAccountsReceived(
- @NonNull Collection accounts) {
- int i = 0;
- FastPairEligibleAccountParcel[] accountParcels =
- new FastPairEligibleAccountParcel[accounts.size()];
- for (FastPairEligibleAccount account: accounts) {
- accountParcels[i] = account.mAccountParcel;
- i = i + 1;
- }
- try {
- mCallback.onFastPairEligibleAccountsReceived(accountParcels);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- } catch (RuntimeException e) {
- Log.w(mTag, e);
- }
- }
-
- @Override
- public void onError(@ErrorCode int code, @Nullable String message) {
- try {
- mCallback.onError(code, message);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- } catch (RuntimeException e) {
- Log.w(mTag, e);
- }
- }
- }
-
- /**
- * Callback class that sends back Fast Pair account management result.
- */
- private final class WrapperFastPairManageAccountCallback implements
- FastPairManageActionCallback {
-
- private IFastPairManageAccountCallback mCallback;
-
- private WrapperFastPairManageAccountCallback(
- IFastPairManageAccountCallback callback) {
- mCallback = callback;
- }
-
- /**
- * Sends back Fast Pair account opt in result.
- */
- @Override
- public void onSuccess() {
- try {
- mCallback.onSuccess();
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- } catch (RuntimeException e) {
- Log.w(mTag, e);
- }
- }
-
- @Override
- public void onError(@ErrorCode int code, @Nullable String message) {
- try {
- mCallback.onError(code, message);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- } catch (RuntimeException e) {
- Log.w(mTag, e);
- }
- }
- }
-
- /**
- * Call back class that sends back account-device mapping management result.
- */
- private final class WrapperFastPairManageAccountDeviceCallback implements
- FastPairManageActionCallback {
-
- private IFastPairManageAccountDeviceCallback mCallback;
-
- private WrapperFastPairManageAccountDeviceCallback(
- IFastPairManageAccountDeviceCallback callback) {
- mCallback = callback;
- }
-
- /**
- * Sends back the account-device mapping management result.
- */
- @Override
- public void onSuccess() {
- try {
- mCallback.onSuccess();
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- } catch (RuntimeException e) {
- Log.w(mTag, e);
- }
- }
-
- @Override
- public void onError(@ErrorCode int code, @Nullable String message) {
- try {
- mCallback.onError(code, message);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- } catch (RuntimeException e) {
- Log.w(mTag, e);
- }
- }
- }
-
- private final class Service extends IFastPairDataProvider.Stub {
-
- Service() {
- }
-
- @Override
- public void loadFastPairAntispoofKeyDeviceMetadata(
- @NonNull FastPairAntispoofKeyDeviceMetadataRequestParcel requestParcel,
- IFastPairAntispoofKeyDeviceMetadataCallback callback) {
- onLoadFastPairAntispoofKeyDeviceMetadata(
- new FastPairAntispoofKeyDeviceMetadataRequest(requestParcel),
- new WrapperFastPairAntispoofKeyDeviceMetadataCallback(callback));
- }
-
- @Override
- public void loadFastPairAccountDevicesMetadata(
- @NonNull FastPairAccountDevicesMetadataRequestParcel requestParcel,
- IFastPairAccountDevicesMetadataCallback callback) {
- onLoadFastPairAccountDevicesMetadata(
- new FastPairAccountDevicesMetadataRequest(requestParcel),
- new WrapperFastPairAccountDevicesMetadataCallback(callback));
- }
-
- @Override
- public void loadFastPairEligibleAccounts(
- @NonNull FastPairEligibleAccountsRequestParcel requestParcel,
- IFastPairEligibleAccountsCallback callback) {
- onLoadFastPairEligibleAccounts(new FastPairEligibleAccountsRequest(requestParcel),
- new WrapperFastPairEligibleAccountsCallback(callback));
- }
-
- @Override
- public void manageFastPairAccount(
- @NonNull FastPairManageAccountRequestParcel requestParcel,
- IFastPairManageAccountCallback callback) {
- onManageFastPairAccount(new FastPairManageAccountRequest(requestParcel),
- new WrapperFastPairManageAccountCallback(callback));
- }
-
- @Override
- public void manageFastPairAccountDevice(
- @NonNull FastPairManageAccountDeviceRequestParcel requestParcel,
- IFastPairManageAccountDeviceCallback callback) {
- onManageFastPairAccountDevice(new FastPairManageAccountDeviceRequest(requestParcel),
- new WrapperFastPairManageAccountDeviceCallback(callback));
- }
- }
-}
diff --git a/nearby/framework/java/android/nearby/FastPairDeviceMetadata.java b/nearby/framework/java/android/nearby/FastPairDeviceMetadata.java
deleted file mode 100644
index 0e2e79d8a67ea7d3d3f0394e143c862d7f1429c6..0000000000000000000000000000000000000000
--- a/nearby/framework/java/android/nearby/FastPairDeviceMetadata.java
+++ /dev/null
@@ -1,683 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.nearby;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.nearby.aidl.FastPairDeviceMetadataParcel;
-
-/**
- * Class for the properties of a given type of Fast Pair device, including images and text.
- *
- * @hide
- */
-public class FastPairDeviceMetadata {
-
- FastPairDeviceMetadataParcel mMetadataParcel;
-
- FastPairDeviceMetadata(
- FastPairDeviceMetadataParcel metadataParcel) {
- this.mMetadataParcel = metadataParcel;
- }
-
- /**
- * Get ImageUrl, which will be displayed in notification.
- *
- * @hide
- */
- @Nullable
- public String getImageUrl() {
- return mMetadataParcel.imageUrl;
- }
-
- /**
- * Get IntentUri, which will be launched to install companion app.
- *
- * @hide
- */
- @Nullable
- public String getIntentUri() {
- return mMetadataParcel.intentUri;
- }
-
- /**
- * Get BLE transmit power, as described in Fast Pair spec, see
- * Transmit Power
- *
- * @hide
- */
- public int getBleTxPower() {
- return mMetadataParcel.bleTxPower;
- }
-
- /**
- * Get Fast Pair Half Sheet trigger distance in meters.
- *
- * @hide
- */
- public float getTriggerDistance() {
- return mMetadataParcel.triggerDistance;
- }
-
- /**
- * Get Fast Pair device image, which is submitted at device registration time to display on
- * notification. It is a 32-bit PNG with dimensions of 512px by 512px.
- *
- * @return Fast Pair device image in 32-bit PNG with dimensions of 512px by 512px.
- * @hide
- */
- @Nullable
- public byte[] getImage() {
- return mMetadataParcel.image;
- }
-
- /**
- * Get Fast Pair device type.
- * DEVICE_TYPE_UNSPECIFIED = 0;
- * HEADPHONES = 1;
- * TRUE_WIRELESS_HEADPHONES = 7;
- * @hide
- */
- public int getDeviceType() {
- return mMetadataParcel.deviceType;
- }
-
- /**
- * Get Fast Pair device name. e.g., "Pixel Buds A-Series".
- *
- * @hide
- */
- @Nullable
- public String getName() {
- return mMetadataParcel.name;
- }
-
- /**
- * Get true wireless image url for left bud.
- *
- * @hide
- */
- @Nullable
- public String getTrueWirelessImageUrlLeftBud() {
- return mMetadataParcel.trueWirelessImageUrlLeftBud;
- }
-
- /**
- * Get true wireless image url for right bud.
- *
- * @hide
- */
- @Nullable
- public String getTrueWirelessImageUrlRightBud() {
- return mMetadataParcel.trueWirelessImageUrlRightBud;
- }
-
- /**
- * Get true wireless image url for case.
- *
- * @hide
- */
- @Nullable
- public String getTrueWirelessImageUrlCase() {
- return mMetadataParcel.trueWirelessImageUrlCase;
- }
-
- /**
- * Get InitialNotificationDescription, which is a translated string of
- * "Tap to pair. Earbuds will be tied to %s" based on locale.
- *
- * @hide
- */
- @Nullable
- public String getInitialNotificationDescription() {
- return mMetadataParcel.initialNotificationDescription;
- }
-
- /**
- * Get InitialNotificationDescriptionNoAccount, which is a translated string of
- * "Tap to pair with this device" based on locale.
- *
- * @hide
- */
- @Nullable
- public String getInitialNotificationDescriptionNoAccount() {
- return mMetadataParcel.initialNotificationDescriptionNoAccount;
- }
-
- /**
- * Get OpenCompanionAppDescription, which is a translated string of
- * "Tap to finish setup" based on locale.
- *
- * @hide
- */
- @Nullable
- public String getOpenCompanionAppDescription() {
- return mMetadataParcel.openCompanionAppDescription;
- }
-
- /**
- * Get UpdateCompanionAppDescription, which is a translated string of
- * "Tap to update device settings and finish setup" based on locale.
- *
- * @hide
- */
- @Nullable
- public String getUpdateCompanionAppDescription() {
- return mMetadataParcel.updateCompanionAppDescription;
- }
-
- /**
- * Get DownloadCompanionAppDescription, which is a translated string of
- * "Tap to download device app on Google Play and see all features" based on locale.
- *
- * @hide
- */
- @Nullable
- public String getDownloadCompanionAppDescription() {
- return mMetadataParcel.downloadCompanionAppDescription;
- }
-
- /**
- * Get UnableToConnectTitle, which is a translated string of
- * "Unable to connect" based on locale.
- */
- @Nullable
- public String getUnableToConnectTitle() {
- return mMetadataParcel.unableToConnectTitle;
- }
-
- /**
- * Get UnableToConnectDescription, which is a translated string of
- * "Try manually pairing to the device" based on locale.
- *
- * @hide
- */
- @Nullable
- public String getUnableToConnectDescription() {
- return mMetadataParcel.unableToConnectDescription;
- }
-
- /**
- * Get InitialPairingDescription, which is a translated string of
- * "%s will appear on devices linked with %s" based on locale.
- *
- * @hide
- */
- @Nullable
- public String getInitialPairingDescription() {
- return mMetadataParcel.initialPairingDescription;
- }
-
- /**
- * Get ConnectSuccessCompanionAppInstalled, which is a translated string of
- * "Your device is ready to be set up" based on locale.
- *
- * @hide
- */
- @Nullable
- public String getConnectSuccessCompanionAppInstalled() {
- return mMetadataParcel.connectSuccessCompanionAppInstalled;
- }
-
- /**
- * Get ConnectSuccessCompanionAppNotInstalled, which is a translated string of
- * "Download the device app on Google Play to see all available features" based on locale.
- *
- * @hide
- */
- @Nullable
- public String getConnectSuccessCompanionAppNotInstalled() {
- return mMetadataParcel.connectSuccessCompanionAppNotInstalled;
- }
-
- /**
- * Get SubsequentPairingDescription, which is a translated string of
- * "Connect %s to this phone" based on locale.
- *
- * @hide
- */
- @Nullable
- public String getSubsequentPairingDescription() {
- return mMetadataParcel.subsequentPairingDescription;
- }
-
- /**
- * Get RetroactivePairingDescription, which is a translated string of
- * "Save device to %s for faster pairing to your other devices" based on locale.
- *
- * @hide
- */
- @Nullable
- public String getRetroactivePairingDescription() {
- return mMetadataParcel.retroactivePairingDescription;
- }
-
- /**
- * Get WaitLaunchCompanionAppDescription, which is a translated string of
- * "This will take a few moments" based on locale.
- *
- * @hide
- */
- @Nullable
- public String getWaitLaunchCompanionAppDescription() {
- return mMetadataParcel.waitLaunchCompanionAppDescription;
- }
-
- /**
- * Get FailConnectGoToSettingsDescription, which is a translated string of
- * "Try manually pairing to the device by going to Settings" based on locale.
- *
- * @hide
- */
- @Nullable
- public String getFailConnectGoToSettingsDescription() {
- return mMetadataParcel.failConnectGoToSettingsDescription;
- }
-
- /**
- * Builder used to create FastPairDeviceMetadata.
- *
- * @hide
- */
- public static final class Builder {
-
- private final FastPairDeviceMetadataParcel mBuilderParcel;
-
- /**
- * Default constructor of Builder.
- *
- * @hide
- */
- public Builder() {
- mBuilderParcel = new FastPairDeviceMetadataParcel();
- mBuilderParcel.imageUrl = null;
- mBuilderParcel.intentUri = null;
- mBuilderParcel.name = null;
- mBuilderParcel.bleTxPower = 0;
- mBuilderParcel.triggerDistance = 0;
- mBuilderParcel.image = null;
- mBuilderParcel.deviceType = 0; // DEVICE_TYPE_UNSPECIFIED
- mBuilderParcel.trueWirelessImageUrlLeftBud = null;
- mBuilderParcel.trueWirelessImageUrlRightBud = null;
- mBuilderParcel.trueWirelessImageUrlCase = null;
- mBuilderParcel.initialNotificationDescription = null;
- mBuilderParcel.initialNotificationDescriptionNoAccount = null;
- mBuilderParcel.openCompanionAppDescription = null;
- mBuilderParcel.updateCompanionAppDescription = null;
- mBuilderParcel.downloadCompanionAppDescription = null;
- mBuilderParcel.unableToConnectTitle = null;
- mBuilderParcel.unableToConnectDescription = null;
- mBuilderParcel.initialPairingDescription = null;
- mBuilderParcel.connectSuccessCompanionAppInstalled = null;
- mBuilderParcel.connectSuccessCompanionAppNotInstalled = null;
- mBuilderParcel.subsequentPairingDescription = null;
- mBuilderParcel.retroactivePairingDescription = null;
- mBuilderParcel.waitLaunchCompanionAppDescription = null;
- mBuilderParcel.failConnectGoToSettingsDescription = null;
- }
-
- /**
- * Set ImageUlr.
- *
- * @param imageUrl Image Ulr.
- * @return The builder, to facilitate chaining {@code builder.setXXX(..).setXXX(..)}.
- * @hide
- */
- @NonNull
- public Builder setImageUrl(@Nullable String imageUrl) {
- mBuilderParcel.imageUrl = imageUrl;
- return this;
- }
-
- /**
- * Set IntentUri.
- *
- * @param intentUri Intent uri.
- * @return The builder, to facilitate chaining {@code builder.setXXX(..).setXXX(..)}.
- * @hide
- */
- @NonNull
- public Builder setIntentUri(@Nullable String intentUri) {
- mBuilderParcel.intentUri = intentUri;
- return this;
- }
-
- /**
- * Set device name.
- *
- * @param name Device name.
- * @return The builder, to facilitate chaining {@code builder.setXXX(..).setXXX(..)}.
- * @hide
- */
- @NonNull
- public Builder setName(@Nullable String name) {
- mBuilderParcel.name = name;
- return this;
- }
-
- /**
- * Set ble transmission power.
- *
- * @param bleTxPower Ble transmission power.
- * @return The builder, to facilitate chaining {@code builder.setXXX(..).setXXX(..)}.
- * @hide
- */
- @NonNull
- public Builder setBleTxPower(int bleTxPower) {
- mBuilderParcel.bleTxPower = bleTxPower;
- return this;
- }
-
- /**
- * Set trigger distance.
- *
- * @param triggerDistance Fast Pair trigger distance.
- * @return The builder, to facilitate chaining {@code builder.setXXX(..).setXXX(..)}.
- * @hide
- */
- @NonNull
- public Builder setTriggerDistance(float triggerDistance) {
- mBuilderParcel.triggerDistance = triggerDistance;
- return this;
- }
-
- /**
- * Set image.
- *
- * @param image Fast Pair device image, which is submitted at device registration time to
- * display on notification. It is a 32-bit PNG with dimensions of
- * 512px by 512px.
- * @return The builder, to facilitate chaining {@code builder.setXXX(..).setXXX(..)}.
- * @hide
- */
- @NonNull
- public Builder setImage(@Nullable byte[] image) {
- mBuilderParcel.image = image;
- return this;
- }
-
- /**
- * Set device type.
- *
- * @param deviceType Fast Pair device type.
- * @return The builder, to facilitate chaining {@code builder.setXXX(..).setXXX(..)}.
- * @hide
- */
- @NonNull
- public Builder setDeviceType(int deviceType) {
- mBuilderParcel.deviceType = deviceType;
- return this;
- }
-
- /**
- * Set true wireless image url for left bud.
- *
- * @param trueWirelessImageUrlLeftBud True wireless image url for left bud.
- * @return The builder, to facilitate chaining {@code builder.setXXX(..).setXXX(..)}.
- * @hide
- */
- @NonNull
- public Builder setTrueWirelessImageUrlLeftBud(
- @Nullable String trueWirelessImageUrlLeftBud) {
- mBuilderParcel.trueWirelessImageUrlLeftBud = trueWirelessImageUrlLeftBud;
- return this;
- }
-
- /**
- * Set true wireless image url for right bud.
- *
- * @param trueWirelessImageUrlRightBud True wireless image url for right bud.
- * @return The builder, to facilitate chaining {@code builder.setXXX(..).setXXX(..)}.
- * @hide
- */
- @NonNull
- public Builder setTrueWirelessImageUrlRightBud(
- @Nullable String trueWirelessImageUrlRightBud) {
- mBuilderParcel.trueWirelessImageUrlRightBud = trueWirelessImageUrlRightBud;
- return this;
- }
-
- /**
- * Set true wireless image url for case.
- *
- * @param trueWirelessImageUrlCase True wireless image url for case.
- * @return The builder, to facilitate chaining {@code builder.setXXX(..).setXXX(..)}.
- * @hide
- */
- @NonNull
- public Builder setTrueWirelessImageUrlCase(@Nullable String trueWirelessImageUrlCase) {
- mBuilderParcel.trueWirelessImageUrlCase = trueWirelessImageUrlCase;
- return this;
- }
-
- /**
- * Set InitialNotificationDescription.
- *
- * @param initialNotificationDescription Initial notification description.
- * @return The builder, to facilitate chaining {@code builder.setXXX(..).setXXX(..)}.
- * @hide
- */
- @NonNull
- public Builder setInitialNotificationDescription(
- @Nullable String initialNotificationDescription) {
- mBuilderParcel.initialNotificationDescription = initialNotificationDescription;
- return this;
- }
-
- /**
- * Set InitialNotificationDescriptionNoAccount.
- *
- * @param initialNotificationDescriptionNoAccount Initial notification description when
- * account is not present.
- * @return The builder, to facilitate chaining {@code builder.setXXX(..).setXXX(..)}.
- * @hide
- */
- @NonNull
- public Builder setInitialNotificationDescriptionNoAccount(
- @Nullable String initialNotificationDescriptionNoAccount) {
- mBuilderParcel.initialNotificationDescriptionNoAccount =
- initialNotificationDescriptionNoAccount;
- return this;
- }
-
- /**
- * Set OpenCompanionAppDescription.
- *
- * @param openCompanionAppDescription Description for opening companion app.
- * @return The builder, to facilitate chaining {@code builder.setXXX(..).setXXX(..)}.
- * @hide
- */
- @NonNull
- public Builder setOpenCompanionAppDescription(
- @Nullable String openCompanionAppDescription) {
- mBuilderParcel.openCompanionAppDescription = openCompanionAppDescription;
- return this;
- }
-
- /**
- * Set UpdateCompanionAppDescription.
- *
- * @param updateCompanionAppDescription Description for updating companion app.
- * @return The builder, to facilitate chaining {@code builder.setXXX(..).setXXX(..)}.
- * @hide
- */
- @NonNull
- public Builder setUpdateCompanionAppDescription(
- @Nullable String updateCompanionAppDescription) {
- mBuilderParcel.updateCompanionAppDescription = updateCompanionAppDescription;
- return this;
- }
-
- /**
- * Set DownloadCompanionAppDescription.
- *
- * @param downloadCompanionAppDescription Description for downloading companion app.
- * @return The builder, to facilitate chaining {@code builder.setXXX(..).setXXX(..)}.
- * @hide
- */
- @NonNull
- public Builder setDownloadCompanionAppDescription(
- @Nullable String downloadCompanionAppDescription) {
- mBuilderParcel.downloadCompanionAppDescription = downloadCompanionAppDescription;
- return this;
- }
-
- /**
- * Set UnableToConnectTitle.
- *
- * @param unableToConnectTitle Title when Fast Pair device is unable to be connected to.
- * @return The builder, to facilitate chaining {@code builder.setXXX(..).setXXX(..)}.
- * @hide
- */
- @NonNull
- public Builder setUnableToConnectTitle(@Nullable String unableToConnectTitle) {
- mBuilderParcel.unableToConnectTitle = unableToConnectTitle;
- return this;
- }
-
- /**
- * Set UnableToConnectDescription.
- *
- * @param unableToConnectDescription Description when Fast Pair device is unable to be
- * connected to.
- * @return The builder, to facilitate chaining {@code builder.setXXX(..).setXXX(..)}.
- * @hide
- */
- @NonNull
- public Builder setUnableToConnectDescription(
- @Nullable String unableToConnectDescription) {
- mBuilderParcel.unableToConnectDescription = unableToConnectDescription;
- return this;
- }
-
- /**
- * Set InitialPairingDescription.
- *
- * @param initialPairingDescription Description for Fast Pair initial pairing.
- * @return The builder, to facilitate chaining {@code builder.setXXX(..).setXXX(..)}.
- * @hide
- */
- @NonNull
- public Builder setInitialPairingDescription(@Nullable String initialPairingDescription) {
- mBuilderParcel.initialPairingDescription = initialPairingDescription;
- return this;
- }
-
- /**
- * Set ConnectSuccessCompanionAppInstalled.
- *
- * @param connectSuccessCompanionAppInstalled Description that let user open the companion
- * app.
- * @return The builder, to facilitate chaining {@code builder.setXXX(..).setXXX(..)}.
- * @hide
- */
- @NonNull
- public Builder setConnectSuccessCompanionAppInstalled(
- @Nullable String connectSuccessCompanionAppInstalled) {
- mBuilderParcel.connectSuccessCompanionAppInstalled =
- connectSuccessCompanionAppInstalled;
- return this;
- }
-
- /**
- * Set ConnectSuccessCompanionAppNotInstalled.
- *
- * @param connectSuccessCompanionAppNotInstalled Description that let user download the
- * companion app.
- * @return The builder, to facilitate chaining {@code builder.setXXX(..).setXXX(..)}.
- * @hide
- */
- @NonNull
- public Builder setConnectSuccessCompanionAppNotInstalled(
- @Nullable String connectSuccessCompanionAppNotInstalled) {
- mBuilderParcel.connectSuccessCompanionAppNotInstalled =
- connectSuccessCompanionAppNotInstalled;
- return this;
- }
-
- /**
- * Set SubsequentPairingDescription.
- *
- * @param subsequentPairingDescription Description that reminds user there is a paired
- * device nearby.
- * @return The builder, to facilitate chaining {@code builder.setXXX(..).setXXX(..)}.
- * @hide
- */
- @NonNull
- public Builder setSubsequentPairingDescription(
- @Nullable String subsequentPairingDescription) {
- mBuilderParcel.subsequentPairingDescription = subsequentPairingDescription;
- return this;
- }
-
- /**
- * Set RetroactivePairingDescription.
- *
- * @param retroactivePairingDescription Description that reminds users opt in their device.
- * @return The builder, to facilitate chaining {@code builder.setXXX(..).setXXX(..)}.
- * @hide
- */
- @NonNull
- public Builder setRetroactivePairingDescription(
- @Nullable String retroactivePairingDescription) {
- mBuilderParcel.retroactivePairingDescription = retroactivePairingDescription;
- return this;
- }
-
- /**
- * Set WaitLaunchCompanionAppDescription.
- *
- * @param waitLaunchCompanionAppDescription Description that indicates companion app is
- * about to launch.
- * @return The builder, to facilitate chaining {@code builder.setXXX(..).setXXX(..)}.
- * @hide
- */
- @NonNull
- public Builder setWaitLaunchCompanionAppDescription(
- @Nullable String waitLaunchCompanionAppDescription) {
- mBuilderParcel.waitLaunchCompanionAppDescription =
- waitLaunchCompanionAppDescription;
- return this;
- }
-
- /**
- * Set FailConnectGoToSettingsDescription.
- *
- * @param failConnectGoToSettingsDescription Description that indicates go to bluetooth
- * settings when connection fail.
- * @return The builder, to facilitate chaining {@code builder.setXXX(..).setXXX(..)}.
- * @hide
- */
- @NonNull
- public Builder setFailConnectGoToSettingsDescription(
- @Nullable String failConnectGoToSettingsDescription) {
- mBuilderParcel.failConnectGoToSettingsDescription =
- failConnectGoToSettingsDescription;
- return this;
- }
-
- /**
- * Build {@link FastPairDeviceMetadata} with the currently set configuration.
- *
- * @hide
- */
- @NonNull
- public FastPairDeviceMetadata build() {
- return new FastPairDeviceMetadata(mBuilderParcel);
- }
- }
-}
diff --git a/nearby/framework/java/android/nearby/FastPairDiscoveryItem.java b/nearby/framework/java/android/nearby/FastPairDiscoveryItem.java
deleted file mode 100644
index d8dfe299688a48d62a17bc0fb3750555b0317a99..0000000000000000000000000000000000000000
--- a/nearby/framework/java/android/nearby/FastPairDiscoveryItem.java
+++ /dev/null
@@ -1,529 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.nearby;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.nearby.aidl.FastPairDiscoveryItemParcel;
-
-/**
- * Class for FastPairDiscoveryItem and its builder.
- *
- * @hide
- */
-public class FastPairDiscoveryItem {
-
- FastPairDiscoveryItemParcel mMetadataParcel;
-
- FastPairDiscoveryItem(
- FastPairDiscoveryItemParcel metadataParcel) {
- this.mMetadataParcel = metadataParcel;
- }
-
- /**
- * Get Id.
- *
- * @hide
- */
- @Nullable
- public String getId() {
- return mMetadataParcel.id;
- }
-
- /**
- * Get MacAddress.
- *
- * @hide
- */
- @Nullable
- public String getMacAddress() {
- return mMetadataParcel.macAddress;
- }
-
- /**
- * Get ActionUrl.
- *
- * @hide
- */
- @Nullable
- public String getActionUrl() {
- return mMetadataParcel.actionUrl;
- }
-
- /**
- * Get DeviceName.
- *
- * @hide
- */
- @Nullable
- public String getDeviceName() {
- return mMetadataParcel.deviceName;
- }
-
- /**
- * Get Title.
- *
- * @hide
- */
- @Nullable
- public String getTitle() {
- return mMetadataParcel.title;
- }
-
- /**
- * Get Description.
- *
- * @hide
- */
- @Nullable
- public String getDescription() {
- return mMetadataParcel.description;
- }
-
- /**
- * Get DisplayUrl.
- *
- * @hide
- */
- @Nullable
- public String getDisplayUrl() {
- return mMetadataParcel.displayUrl;
- }
-
- /**
- * Get LastObservationTimestampMillis.
- *
- * @hide
- */
- public long getLastObservationTimestampMillis() {
- return mMetadataParcel.lastObservationTimestampMillis;
- }
-
- /**
- * Get FirstObservationTimestampMillis.
- *
- * @hide
- */
- public long getFirstObservationTimestampMillis() {
- return mMetadataParcel.firstObservationTimestampMillis;
- }
-
- /**
- * Get State.
- *
- * @hide
- */
- public int getState() {
- return mMetadataParcel.state;
- }
-
- /**
- * Get ActionUrlType.
- *
- * @hide
- */
- public int getActionUrlType() {
- return mMetadataParcel.actionUrlType;
- }
-
- /**
- * Get Rssi.
- *
- * @hide
- */
- public int getRssi() {
- return mMetadataParcel.rssi;
- }
-
- /**
- * Get PendingAppInstallTimestampMillis.
- *
- * @hide
- */
- public long getPendingAppInstallTimestampMillis() {
- return mMetadataParcel.pendingAppInstallTimestampMillis;
- }
-
- /**
- * Get TxPower.
- *
- * @hide
- */
- public int getTxPower() {
- return mMetadataParcel.txPower;
- }
-
- /**
- * Get AppName.
- *
- * @hide
- */
- @Nullable
- public String getAppName() {
- return mMetadataParcel.appName;
- }
-
- /**
- * Get PackageName.
- *
- * @hide
- */
- @Nullable
- public String getPackageName() {
- return mMetadataParcel.packageName;
- }
-
- /**
- * Get TriggerId.
- *
- * @hide
- */
- @Nullable
- public String getTriggerId() {
- return mMetadataParcel.triggerId;
- }
-
- /**
- * Get IconPng, which is submitted at device registration time to display on notification. It is
- * a 32-bit PNG with dimensions of 512px by 512px.
- *
- * @return IconPng in 32-bit PNG with dimensions of 512px by 512px.
- * @hide
- */
- @Nullable
- public byte[] getIconPng() {
- return mMetadataParcel.iconPng;
- }
-
- /**
- * Get IconFifeUrl.
- *
- * @hide
- */
- @Nullable
- public String getIconFfeUrl() {
- return mMetadataParcel.iconFifeUrl;
- }
-
- /**
- * Get authenticationPublicKeySecp256r1, which is same as AntiSpoof public key, see
- * Data Format.
- *
- * @return 64-byte authenticationPublicKeySecp256r1.
- * @hide
- */
- @Nullable
- public byte[] getAuthenticationPublicKeySecp256r1() {
- return mMetadataParcel.authenticationPublicKeySecp256r1;
- }
-
- /**
- * Builder used to create FastPairDiscoveryItem.
- *
- * @hide
- */
- public static final class Builder {
-
- private final FastPairDiscoveryItemParcel mBuilderParcel;
-
- /**
- * Default constructor of Builder.
- *
- * @hide
- */
- public Builder() {
- mBuilderParcel = new FastPairDiscoveryItemParcel();
- }
-
- /**
- * Set Id.
- *
- * @param id Unique id.
- * @return The builder, to facilitate chaining {@code builder.setXXX(..).setXXX(..)}.
- *
- * @hide
- */
- @NonNull
- public Builder setId(@Nullable String id) {
- mBuilderParcel.id = id;
- return this;
- }
-
- /**
- * Set MacAddress.
- *
- * @param macAddress Fast Pair device rotating mac address.
- * @return The builder, to facilitate chaining {@code builder.setXXX(..).setXXX(..)}.
- * @hide
- */
- @NonNull
- public Builder setMacAddress(@Nullable String macAddress) {
- mBuilderParcel.macAddress = macAddress;
- return this;
- }
-
- /**
- * Set ActionUrl.
- *
- * @param actionUrl Action Url of Fast Pair device.
- * @return The builder, to facilitate chaining {@code builder.setXXX(..).setXXX(..)}.
- * @hide
- */
- @NonNull
- public Builder setActionUrl(@Nullable String actionUrl) {
- mBuilderParcel.actionUrl = actionUrl;
- return this;
- }
-
- /**
- * Set DeviceName.
- * @param deviceName Fast Pair device name.
- * @return The builder, to facilitate chaining {@code builder.setXXX(..).setXXX(..)}.
- * @hide
- */
- @NonNull
- public Builder setDeviceName(@Nullable String deviceName) {
- mBuilderParcel.deviceName = deviceName;
- return this;
- }
-
- /**
- * Set Title.
- *
- * @param title Title of Fast Pair device.
- * @return The builder, to facilitate chaining {@code builder.setXXX(..).setXXX(..)}.
- * @hide
- */
- @NonNull
- public Builder setTitle(@Nullable String title) {
- mBuilderParcel.title = title;
- return this;
- }
-
- /**
- * Set Description.
- *
- * @param description Description of Fast Pair device.
- * @return The builder, to facilitate chaining {@code builder.setXXX(..).setXXX(..)}.
- * @hide
- */
- @NonNull
- public Builder setDescription(@Nullable String description) {
- mBuilderParcel.description = description;
- return this;
- }
-
- /**
- * Set DisplayUrl.
- *
- * @param displayUrl Display Url of Fast Pair device.
- * @return The builder, to facilitate chaining {@code builder.setXXX(..).setXXX(..)}.
- * @hide
- */
- @NonNull
- public Builder setDisplayUrl(@Nullable String displayUrl) {
- mBuilderParcel.displayUrl = displayUrl;
- return this;
- }
-
- /**
- * Set LastObservationTimestampMillis.
- *
- * @param lastObservationTimestampMillis Last observed timestamp of Fast Pair device, keyed
- * by a rotating id.
- * @return The builder, to facilitate chaining {@code builder.setXXX(..).setXXX(..)}.
- * @hide
- */
- @NonNull
- public Builder setLastObservationTimestampMillis(
- long lastObservationTimestampMillis) {
- mBuilderParcel.lastObservationTimestampMillis = lastObservationTimestampMillis;
- return this;
- }
-
- /**
- * Set FirstObservationTimestampMillis.
- *
- * @param firstObservationTimestampMillis First observed timestamp of Fast Pair device,
- * keyed by a rotating id.
- * @return The builder, to facilitate chaining {@code builder.setXXX(..).setXXX(..)}.
- * @hide
- */
- @NonNull
- public Builder setFirstObservationTimestampMillis(
- long firstObservationTimestampMillis) {
- mBuilderParcel.firstObservationTimestampMillis = firstObservationTimestampMillis;
- return this;
- }
-
- /**
- * Set State.
- *
- * @param state Item's current state. e.g. if the item is blocked.
- * @return The builder, to facilitate chaining {@code builder.setXXX(..).setXXX(..)}.
- * @hide
- */
- @NonNull
- public Builder setState(int state) {
- mBuilderParcel.state = state;
- return this;
- }
-
- /**
- * Set ActionUrlType.
- *
- * @param actionUrlType The resolved url type for the action_url.
- * @return The builder, to facilitate chaining {@code builder.setXXX(..).setXXX(..)}.
- * @hide
- */
- @NonNull
- public Builder setActionUrlType(int actionUrlType) {
- mBuilderParcel.actionUrlType = actionUrlType;
- return this;
- }
-
- /**
- * Set Rssi.
- *
- * @param rssi Beacon's RSSI value.
- * @return The builder, to facilitate chaining {@code builder.setXXX(..).setXXX(..)}.
- * @hide
- */
- @NonNull
- public Builder setRssi(int rssi) {
- mBuilderParcel.rssi = rssi;
- return this;
- }
-
- /**
- * Set PendingAppInstallTimestampMillis.
- *
- * @param pendingAppInstallTimestampMillis The timestamp when the user is redirected to App
- * Store after clicking on the item.
- * @return The builder, to facilitate chaining {@code builder.setXXX(..).setXXX(..)}.
- * @hide
- */
- @NonNull
- public Builder setPendingAppInstallTimestampMillis(long pendingAppInstallTimestampMillis) {
- mBuilderParcel.pendingAppInstallTimestampMillis = pendingAppInstallTimestampMillis;
- return this;
- }
-
- /**
- * Set TxPower.
- *
- * @param txPower Beacon's tx power.
- * @return The builder, to facilitate chaining {@code builder.setXXX(..).setXXX(..)}.
- * @hide
- */
- @NonNull
- public Builder setTxPower(int txPower) {
- mBuilderParcel.txPower = txPower;
- return this;
- }
-
- /**
- * Set AppName.
- *
- * @param appName Human readable name of the app designated to open the uri.
- * @return The builder, to facilitate chaining {@code builder.setXXX(..).setXXX(..)}.
- * @hide
- */
- @NonNull
- public Builder setAppName(@Nullable String appName) {
- mBuilderParcel.appName = appName;
- return this;
- }
-
- /**
- * Set PackageName.
- *
- * @param packageName Package name of the App that owns this item.
- * @return The builder, to facilitate chaining {@code builder.setXXX(..).setXXX(..)}.
- * @hide
- */
- @NonNull
- public Builder setPackageName(@Nullable String packageName) {
- mBuilderParcel.packageName = packageName;
- return this;
- }
-
- /**
- * Set TriggerId.
- *
- * @param triggerId TriggerId identifies the trigger/beacon that is attached with a message.
- * @return The builder, to facilitate chaining {@code builder.setXXX(..).setXXX(..)}.
- * @hide
- */
- @NonNull
- public Builder setTriggerId(@Nullable String triggerId) {
- mBuilderParcel.triggerId = triggerId;
- return this;
- }
-
- /**
- * Set IconPng.
- *
- * @param iconPng Bytes of item icon in PNG format displayed in Discovery item list.
- * @return The builder, to facilitate chaining {@code builder.setXXX(..).setXXX(..)}.
- * @hide
- */
- @NonNull
- public Builder setIconPng(@Nullable byte[] iconPng) {
- mBuilderParcel.iconPng = iconPng;
- return this;
- }
-
- /**
- * Set IconFifeUrl.
- *
- * @param iconFifeUrl A FIFE URL of the item icon displayed in Discovery item list.
- * @return The builder, to facilitate chaining {@code builder.setXXX(..).setXXX(..)}.
- * @hide
- */
- @NonNull
- public Builder setIconFfeUrl(@Nullable String iconFifeUrl) {
- mBuilderParcel.iconFifeUrl = iconFifeUrl;
- return this;
- }
-
- /**
- * Set authenticationPublicKeySecp256r1, which is same as AntiSpoof public key, see
- * Data Format
- *
- * @param authenticationPublicKeySecp256r1 64-byte Fast Pair device public key.
- * @return The builder, to facilitate chaining {@code builder.setXXX(..).setXXX(..)}.
- * @hide
- */
- @NonNull
- public Builder setAuthenticationPublicKeySecp256r1(
- @Nullable byte[] authenticationPublicKeySecp256r1) {
- mBuilderParcel.authenticationPublicKeySecp256r1 = authenticationPublicKeySecp256r1;
- return this;
- }
-
- /**
- * Build {@link FastPairDiscoveryItem} with the currently set configuration.
- *
- * @hide
- */
- @NonNull
- public FastPairDiscoveryItem build() {
- return new FastPairDiscoveryItem(mBuilderParcel);
- }
- }
-}
diff --git a/nearby/framework/java/android/nearby/FastPairEligibleAccount.java b/nearby/framework/java/android/nearby/FastPairEligibleAccount.java
deleted file mode 100644
index 8be4cca8e8993e40ca5464a0af9df4c6214dd88d..0000000000000000000000000000000000000000
--- a/nearby/framework/java/android/nearby/FastPairEligibleAccount.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.nearby;
-
-import android.accounts.Account;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.nearby.aidl.FastPairEligibleAccountParcel;
-
-/**
- * Class for FastPairEligibleAccount and its builder.
- *
- * @hide
- */
-public class FastPairEligibleAccount {
-
- FastPairEligibleAccountParcel mAccountParcel;
-
- FastPairEligibleAccount(FastPairEligibleAccountParcel accountParcel) {
- this.mAccountParcel = accountParcel;
- }
-
- /**
- * Get Account.
- *
- * @hide
- */
- @Nullable
- public Account getAccount() {
- return this.mAccountParcel.account;
- }
-
- /**
- * Get OptIn Status.
- *
- * @hide
- */
- public boolean isOptIn() {
- return this.mAccountParcel.optIn;
- }
-
- /**
- * Builder used to create FastPairEligibleAccount.
- *
- * @hide
- */
- public static final class Builder {
-
- private final FastPairEligibleAccountParcel mBuilderParcel;
-
- /**
- * Default constructor of Builder.
- *
- * @hide
- */
- public Builder() {
- mBuilderParcel = new FastPairEligibleAccountParcel();
- mBuilderParcel.account = null;
- mBuilderParcel.optIn = false;
- }
-
- /**
- * Set Account.
- *
- * @param account Fast Pair eligible account.
- * @return The builder, to facilitate chaining {@code builder.setXXX(..).setXXX(..)}.
- * @hide
- */
- @NonNull
- public Builder setAccount(@Nullable Account account) {
- mBuilderParcel.account = account;
- return this;
- }
-
- /**
- * Set whether the account is opt into Fast Pair.
- *
- * @param optIn Whether the Fast Pair eligible account opts into Fast Pair.
- * @return The builder, to facilitate chaining {@code builder.setXXX(..).setXXX(..)}.
- * @hide
- */
- @NonNull
- public Builder setOptIn(boolean optIn) {
- mBuilderParcel.optIn = optIn;
- return this;
- }
-
- /**
- * Build {@link FastPairEligibleAccount} with the currently set configuration.
- *
- * @hide
- */
- @NonNull
- public FastPairEligibleAccount build() {
- return new FastPairEligibleAccount(mBuilderParcel);
- }
- }
-}
diff --git a/nearby/framework/java/android/nearby/FastPairStatusCallback.java b/nearby/framework/java/android/nearby/FastPairStatusCallback.java
deleted file mode 100644
index 1567828695a8e94217d4155d5617de3394f1f64e..0000000000000000000000000000000000000000
--- a/nearby/framework/java/android/nearby/FastPairStatusCallback.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.nearby;
-
-import android.annotation.NonNull;
-
-/**
- * Reports the pair status for an ongoing pair with a {@link FastPairDevice}.
- * @hide
- */
-public interface FastPairStatusCallback {
-
- /** Reports a pair status related metadata associated with a {@link FastPairDevice} */
- void onPairUpdate(@NonNull FastPairDevice fastPairDevice,
- PairStatusMetadata pairStatusMetadata);
-}
diff --git a/nearby/framework/java/android/nearby/IFastPairHalfSheetCallback.aidl b/nearby/framework/java/android/nearby/IFastPairHalfSheetCallback.aidl
deleted file mode 100644
index 2e6fc879261778a5b5fbe57008f3a85fbc0d3ec5..0000000000000000000000000000000000000000
--- a/nearby/framework/java/android/nearby/IFastPairHalfSheetCallback.aidl
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (C) 2021 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package android.nearby;
-
-import android.content.Intent;
-/**
- * Provides callback interface for halfsheet to send FastPair call back.
- *
- * {@hide}
- */
-interface IFastPairHalfSheetCallback {
- void onHalfSheetConnectionConfirm(in Intent intent);
- }
\ No newline at end of file
diff --git a/nearby/framework/java/android/nearby/PairStatusMetadata.aidl b/nearby/framework/java/android/nearby/PairStatusMetadata.aidl
deleted file mode 100644
index 911a30089f25188dcfb0fe58a3a5a9a989181544..0000000000000000000000000000000000000000
--- a/nearby/framework/java/android/nearby/PairStatusMetadata.aidl
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright (C) 2022, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.nearby;
-
-/**
- * Metadata about an ongoing paring. Wraps transient data like status and progress.
- *
- * @hide
- */
-parcelable PairStatusMetadata;
diff --git a/nearby/framework/java/android/nearby/PairStatusMetadata.java b/nearby/framework/java/android/nearby/PairStatusMetadata.java
deleted file mode 100644
index 438cd6b46fc0096fe0d22ce30252a4c5f07f7bc0..0000000000000000000000000000000000000000
--- a/nearby/framework/java/android/nearby/PairStatusMetadata.java
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.nearby;
-
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.util.Objects;
-
-/**
- * Metadata about an ongoing paring. Wraps transient data like status and progress.
- *
- * @hide
- */
-public final class PairStatusMetadata implements Parcelable {
-
- @Status
- private final int mStatus;
-
- /** The status of the pairing. */
- @IntDef({
- Status.UNKNOWN,
- Status.SUCCESS,
- Status.FAIL,
- Status.DISMISS
- })
- public @interface Status {
- int UNKNOWN = 1000;
- int SUCCESS = 1001;
- int FAIL = 1002;
- int DISMISS = 1003;
- }
-
- /** Converts the status to readable string. */
- public static String statusToString(@Status int status) {
- switch (status) {
- case Status.SUCCESS:
- return "SUCCESS";
- case Status.FAIL:
- return "FAIL";
- case Status.DISMISS:
- return "DISMISS";
- case Status.UNKNOWN:
- default:
- return "UNKNOWN";
- }
- }
-
- public int getStatus() {
- return mStatus;
- }
-
- @Override
- public String toString() {
- return "PairStatusMetadata[ status=" + statusToString(mStatus) + "]";
- }
-
- @Override
- public boolean equals(Object other) {
- if (other instanceof PairStatusMetadata) {
- return mStatus == ((PairStatusMetadata) other).mStatus;
- }
- return false;
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(mStatus);
- }
-
- public PairStatusMetadata(@Status int status) {
- mStatus = status;
- }
-
- public static final Creator CREATOR = new Creator() {
- @Override
- public PairStatusMetadata createFromParcel(Parcel in) {
- return new PairStatusMetadata(in.readInt());
- }
-
- @Override
- public PairStatusMetadata[] newArray(int size) {
- return new PairStatusMetadata[size];
- }
- };
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public int getStability() {
- return 0;
- }
-
- @Override
- public void writeToParcel(@NonNull Parcel dest, int flags) {
- dest.writeInt(mStatus);
- }
-}
diff --git a/nearby/framework/java/android/nearby/aidl/ByteArrayParcel.aidl b/nearby/framework/java/android/nearby/aidl/ByteArrayParcel.aidl
deleted file mode 100644
index 53c73bdf6ee3947704f5cbf16ab4d79afa569d5b..0000000000000000000000000000000000000000
--- a/nearby/framework/java/android/nearby/aidl/ByteArrayParcel.aidl
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.nearby.aidl;
-
-/**
- * This is to support 2D byte arrays.
- * {@hide}
- */
-parcelable ByteArrayParcel {
- byte[] byteArray;
-}
\ No newline at end of file
diff --git a/nearby/framework/java/android/nearby/aidl/FastPairAccountDevicesMetadataRequestParcel.aidl b/nearby/framework/java/android/nearby/aidl/FastPairAccountDevicesMetadataRequestParcel.aidl
deleted file mode 100644
index fc3ba22e0873fe17f6f3949165b794e8f482720d..0000000000000000000000000000000000000000
--- a/nearby/framework/java/android/nearby/aidl/FastPairAccountDevicesMetadataRequestParcel.aidl
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.nearby.aidl;
-
-import android.accounts.Account;
-import android.nearby.aidl.ByteArrayParcel;
-
-/**
- * Request details for Metadata of Fast Pair devices associated with an account.
- * {@hide}
- */
-parcelable FastPairAccountDevicesMetadataRequestParcel {
- Account account;
- ByteArrayParcel[] deviceAccountKeys;
-}
\ No newline at end of file
diff --git a/nearby/framework/java/android/nearby/aidl/FastPairAccountKeyDeviceMetadataParcel.aidl b/nearby/framework/java/android/nearby/aidl/FastPairAccountKeyDeviceMetadataParcel.aidl
deleted file mode 100644
index 80143232af215eceedcf06439d91b36463515a9d..0000000000000000000000000000000000000000
--- a/nearby/framework/java/android/nearby/aidl/FastPairAccountKeyDeviceMetadataParcel.aidl
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright (C) 2021 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package android.nearby.aidl;
-
-import android.nearby.aidl.FastPairDeviceMetadataParcel;
-import android.nearby.aidl.FastPairDiscoveryItemParcel;
-
-/**
- * Metadata of a Fast Pair device associated with an account.
- * {@hide}
- */
- // TODO(b/204780849): remove unnecessary fields and polish comments.
-parcelable FastPairAccountKeyDeviceMetadataParcel {
- // Key of the Fast Pair device associated with the account.
- byte[] deviceAccountKey;
- // Hash function of device account key and public bluetooth address.
- byte[] sha256DeviceAccountKeyPublicAddress;
- // Fast Pair device metadata for the Fast Pair device.
- FastPairDeviceMetadataParcel metadata;
- // Fast Pair discovery item tied to both the Fast Pair device and the
- // account.
- FastPairDiscoveryItemParcel discoveryItem;
-}
\ No newline at end of file
diff --git a/nearby/framework/java/android/nearby/aidl/FastPairAntispoofKeyDeviceMetadataParcel.aidl b/nearby/framework/java/android/nearby/aidl/FastPairAntispoofKeyDeviceMetadataParcel.aidl
deleted file mode 100644
index 4fd4d4b83ffd58dabea40617bec559b06ec0d629..0000000000000000000000000000000000000000
--- a/nearby/framework/java/android/nearby/aidl/FastPairAntispoofKeyDeviceMetadataParcel.aidl
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright (C) 2021 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package android.nearby.aidl;
-
-import android.nearby.aidl.FastPairDeviceMetadataParcel;
-
-/**
- * Metadata of a Fast Pair device keyed by AntispoofKey,
- * Used by initial pairing without account association.
- *
- * {@hide}
- */
-parcelable FastPairAntispoofKeyDeviceMetadataParcel {
- // Anti-spoof public key.
- byte[] antispoofPublicKey;
-
- // Fast Pair device metadata for the Fast Pair device.
- FastPairDeviceMetadataParcel deviceMetadata;
-}
\ No newline at end of file
diff --git a/nearby/framework/java/android/nearby/aidl/FastPairAntispoofKeyDeviceMetadataRequestParcel.aidl b/nearby/framework/java/android/nearby/aidl/FastPairAntispoofKeyDeviceMetadataRequestParcel.aidl
deleted file mode 100644
index afdcf154aa604be30aacb6c7a91b7b24df5faef6..0000000000000000000000000000000000000000
--- a/nearby/framework/java/android/nearby/aidl/FastPairAntispoofKeyDeviceMetadataRequestParcel.aidl
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.nearby.aidl;
-
-/**
- * Request details for metadata of a Fast Pair device keyed by either
- * antispoofKey or modelId.
- * {@hide}
- */
-parcelable FastPairAntispoofKeyDeviceMetadataRequestParcel {
- byte[] modelId;
-}
\ No newline at end of file
diff --git a/nearby/framework/java/android/nearby/aidl/FastPairDeviceMetadataParcel.aidl b/nearby/framework/java/android/nearby/aidl/FastPairDeviceMetadataParcel.aidl
deleted file mode 100644
index d90f6a1d8b5e219e580f8308731bc6e4c65aa96b..0000000000000000000000000000000000000000
--- a/nearby/framework/java/android/nearby/aidl/FastPairDeviceMetadataParcel.aidl
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.nearby.aidl;
-
-/**
- * Fast Pair Device Metadata for a given device model ID.
- * @hide
- */
-// TODO(b/204780849): remove unnecessary fields and polish comments.
-parcelable FastPairDeviceMetadataParcel {
- // The image to show on the notification.
- String imageUrl;
-
- // The intent that will be launched via the notification.
- String intentUri;
-
- // The transmit power of the device's BLE chip.
- int bleTxPower;
-
- // The distance that the device must be within to show a notification.
- // If no distance is set, we default to 0.6 meters. Only Nearby admins can
- // change this.
- float triggerDistance;
-
- // The image icon that shows in the notification.
- byte[] image;
-
- // The name of the device.
- String name;
-
- int deviceType;
-
- // The image urls for device with device type "true wireless".
- String trueWirelessImageUrlLeftBud;
- String trueWirelessImageUrlRightBud;
- String trueWirelessImageUrlCase;
-
- // The notification description for when the device is initially discovered.
- String initialNotificationDescription;
-
- // The notification description for when the device is initially discovered
- // and no account is logged in.
- String initialNotificationDescriptionNoAccount;
-
- // The notification description for once we have finished pairing and the
- // companion app has been opened. For Bisto devices, this String will point
- // users to setting up the assistant.
- String openCompanionAppDescription;
-
- // The notification description for once we have finished pairing and the
- // companion app needs to be updated before use.
- String updateCompanionAppDescription;
-
- // The notification description for once we have finished pairing and the
- // companion app needs to be installed.
- String downloadCompanionAppDescription;
-
- // The notification title when a pairing fails.
- String unableToConnectTitle;
-
- // The notification summary when a pairing fails.
- String unableToConnectDescription;
-
- // The description that helps user initially paired with device.
- String initialPairingDescription;
-
- // The description that let user open the companion app.
- String connectSuccessCompanionAppInstalled;
-
- // The description that let user download the companion app.
- String connectSuccessCompanionAppNotInstalled;
-
- // The description that reminds user there is a paired device nearby.
- String subsequentPairingDescription;
-
- // The description that reminds users opt in their device.
- String retroactivePairingDescription;
-
- // The description that indicates companion app is about to launch.
- String waitLaunchCompanionAppDescription;
-
- // The description that indicates go to bluetooth settings when connection
- // fail.
- String failConnectGoToSettingsDescription;
-}
\ No newline at end of file
diff --git a/nearby/framework/java/android/nearby/aidl/FastPairDiscoveryItemParcel.aidl b/nearby/framework/java/android/nearby/aidl/FastPairDiscoveryItemParcel.aidl
deleted file mode 100644
index 2cc2daad00a68a86d5190c619b55aaaa21f9a528..0000000000000000000000000000000000000000
--- a/nearby/framework/java/android/nearby/aidl/FastPairDiscoveryItemParcel.aidl
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.nearby.aidl;
-
-/**
- * Fast Pair Discovery Item.
- * @hide
- */
-// TODO(b/204780849): remove unnecessary fields and polish comments.
-parcelable FastPairDiscoveryItemParcel {
- // Offline item: unique ID generated on client.
- // Online item: unique ID generated on server.
- String id;
-
- // The most recent all upper case mac associated with this item.
- // (Mac-to-DiscoveryItem is a many-to-many relationship)
- String macAddress;
-
- String actionUrl;
-
- // The bluetooth device name from advertisement
- String deviceName;
-
- // Item's title
- String title;
-
- // Item's description.
- String description;
-
- // The URL for display
- String displayUrl;
-
- // Client timestamp when the beacon was last observed in BLE scan.
- long lastObservationTimestampMillis;
-
- // Client timestamp when the beacon was first observed in BLE scan.
- long firstObservationTimestampMillis;
-
- // Item's current state. e.g. if the item is blocked.
- int state;
-
- // The resolved url type for the action_url.
- int actionUrlType;
-
- // The timestamp when the user is redirected to Play Store after clicking on
- // the item.
- long pendingAppInstallTimestampMillis;
-
- // Beacon's RSSI value
- int rssi;
-
- // Beacon's tx power
- int txPower;
-
- // Human readable name of the app designated to open the uri
- // Used in the second line of the notification, "Open in {} app"
- String appName;
-
- // Package name of the App that owns this item.
- String packageName;
-
- // TriggerId identifies the trigger/beacon that is attached with a message.
- // It's generated from server for online messages to synchronize formatting
- // across client versions.
- // Example:
- // * BLE_UID: 3||deadbeef
- // * BLE_URL: http://trigger.id
- // See go/discovery-store-message-and-trigger-id for more details.
- String triggerId;
-
- // Bytes of item icon in PNG format displayed in Discovery item list.
- byte[] iconPng;
-
- // A FIFE URL of the item icon displayed in Discovery item list.
- String iconFifeUrl;
-
- // Fast Pair antispoof key.
- byte[] authenticationPublicKeySecp256r1;
-}
\ No newline at end of file
diff --git a/nearby/framework/java/android/nearby/aidl/FastPairEligibleAccountParcel.aidl b/nearby/framework/java/android/nearby/aidl/FastPairEligibleAccountParcel.aidl
deleted file mode 100644
index 747758d03277960a8756557d22c3328057a2b21f..0000000000000000000000000000000000000000
--- a/nearby/framework/java/android/nearby/aidl/FastPairEligibleAccountParcel.aidl
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.nearby.aidl;
-
-import android.accounts.Account;
-
-/**
- * Fast Pair Eligible Account.
- * {@hide}
- */
-parcelable FastPairEligibleAccountParcel {
- Account account;
- // Whether the account opts in Fast Pair.
- boolean optIn;
-}
\ No newline at end of file
diff --git a/nearby/framework/java/android/nearby/aidl/FastPairEligibleAccountsRequestParcel.aidl b/nearby/framework/java/android/nearby/aidl/FastPairEligibleAccountsRequestParcel.aidl
deleted file mode 100644
index 8db335602474bbf4b8abe6d84ac4c8f90bfb92ed..0000000000000000000000000000000000000000
--- a/nearby/framework/java/android/nearby/aidl/FastPairEligibleAccountsRequestParcel.aidl
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.nearby.aidl;
-
-/**
- * Request details for Fast Pair eligible accounts.
- * Empty place holder for future expansion.
- * {@hide}
- */
-parcelable FastPairEligibleAccountsRequestParcel {
-}
\ No newline at end of file
diff --git a/nearby/framework/java/android/nearby/aidl/FastPairManageAccountDeviceRequestParcel.aidl b/nearby/framework/java/android/nearby/aidl/FastPairManageAccountDeviceRequestParcel.aidl
deleted file mode 100644
index 59834b2839fa1b167d4bf040241e7b4371fb2eb9..0000000000000000000000000000000000000000
--- a/nearby/framework/java/android/nearby/aidl/FastPairManageAccountDeviceRequestParcel.aidl
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.nearby.aidl;
-
-import android.accounts.Account;
-import android.nearby.aidl.FastPairAccountKeyDeviceMetadataParcel;
-
-/**
- * Request details for managing Fast Pair device-account mapping.
- * {@hide}
- */
- // TODO(b/204780849): remove unnecessary fields and polish comments.
-parcelable FastPairManageAccountDeviceRequestParcel {
- Account account;
- // MANAGE_ACCOUNT_DEVICE_ADD: add Fast Pair device to the account.
- // MANAGE_ACCOUNT_DEVICE_REMOVE: remove Fast Pair device from the account.
- int requestType;
- // Fast Pair account key-ed device metadata.
- FastPairAccountKeyDeviceMetadataParcel accountKeyDeviceMetadata;
-}
\ No newline at end of file
diff --git a/nearby/framework/java/android/nearby/aidl/FastPairManageAccountRequestParcel.aidl b/nearby/framework/java/android/nearby/aidl/FastPairManageAccountRequestParcel.aidl
deleted file mode 100644
index 3d9206464dc7247c4e534faa45284e2c3bcafb44..0000000000000000000000000000000000000000
--- a/nearby/framework/java/android/nearby/aidl/FastPairManageAccountRequestParcel.aidl
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.nearby.aidl;
-
-import android.accounts.Account;
-
-/**
- * Request details for managing a Fast Pair account.
- *
- * {@hide}
- */
-parcelable FastPairManageAccountRequestParcel {
- Account account;
- // MANAGE_ACCOUNT_OPT_IN: opt account into Fast Pair.
- // MANAGE_ACCOUNT_OPT_OUT: opt account out of Fast Pair.
- int requestType;
-}
\ No newline at end of file
diff --git a/nearby/framework/java/android/nearby/aidl/IFastPairAccountDevicesMetadataCallback.aidl b/nearby/framework/java/android/nearby/aidl/IFastPairAccountDevicesMetadataCallback.aidl
deleted file mode 100644
index 7db18d00106503c2fd656e80f4434c89cad2b676..0000000000000000000000000000000000000000
--- a/nearby/framework/java/android/nearby/aidl/IFastPairAccountDevicesMetadataCallback.aidl
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright (C) 2021 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package android.nearby.aidl;
-
-import android.nearby.aidl.FastPairAccountKeyDeviceMetadataParcel;
-
-/**
- * Provides callback interface for OEMs to send back metadata of FastPair
- * devices associated with an account.
- *
- * {@hide}
- */
-interface IFastPairAccountDevicesMetadataCallback {
- void onFastPairAccountDevicesMetadataReceived(in FastPairAccountKeyDeviceMetadataParcel[] accountDevicesMetadata);
- void onError(int code, String message);
-}
\ No newline at end of file
diff --git a/nearby/framework/java/android/nearby/aidl/IFastPairAntispoofKeyDeviceMetadataCallback.aidl b/nearby/framework/java/android/nearby/aidl/IFastPairAntispoofKeyDeviceMetadataCallback.aidl
deleted file mode 100644
index 38abba4fb1baccfc66a899e01d42b0f19792984b..0000000000000000000000000000000000000000
--- a/nearby/framework/java/android/nearby/aidl/IFastPairAntispoofKeyDeviceMetadataCallback.aidl
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright (C) 2021 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package android.nearby.aidl;
-
-import android.nearby.aidl.FastPairAntispoofKeyDeviceMetadataParcel;
-
-/**
- * Provides callback interface for OEMs to send FastPair AntispoofKey Device metadata back.
- *
- * {@hide}
- */
-interface IFastPairAntispoofKeyDeviceMetadataCallback {
- void onFastPairAntispoofKeyDeviceMetadataReceived(in FastPairAntispoofKeyDeviceMetadataParcel metadata);
- void onError(int code, String message);
-}
\ No newline at end of file
diff --git a/nearby/framework/java/android/nearby/aidl/IFastPairDataProvider.aidl b/nearby/framework/java/android/nearby/aidl/IFastPairDataProvider.aidl
deleted file mode 100644
index 295621188c15337d7d871e5847c45df91c6b9592..0000000000000000000000000000000000000000
--- a/nearby/framework/java/android/nearby/aidl/IFastPairDataProvider.aidl
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright (C) 2021 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package android.nearby.aidl;
-
-import android.nearby.aidl.FastPairAntispoofKeyDeviceMetadataRequestParcel;
-import android.nearby.aidl.IFastPairAntispoofKeyDeviceMetadataCallback;
-import android.nearby.aidl.FastPairAccountDevicesMetadataRequestParcel;
-import android.nearby.aidl.IFastPairAccountDevicesMetadataCallback;
-import android.nearby.aidl.FastPairEligibleAccountsRequestParcel;
-import android.nearby.aidl.IFastPairEligibleAccountsCallback;
-import android.nearby.aidl.FastPairManageAccountRequestParcel;
-import android.nearby.aidl.IFastPairManageAccountCallback;
-import android.nearby.aidl.FastPairManageAccountDeviceRequestParcel;
-import android.nearby.aidl.IFastPairManageAccountDeviceCallback;
-
-/**
- * Interface for communicating with the fast pair providers.
- *
- * {@hide}
- */
-oneway interface IFastPairDataProvider {
- void loadFastPairAntispoofKeyDeviceMetadata(in FastPairAntispoofKeyDeviceMetadataRequestParcel request,
- in IFastPairAntispoofKeyDeviceMetadataCallback callback);
- void loadFastPairAccountDevicesMetadata(in FastPairAccountDevicesMetadataRequestParcel request,
- in IFastPairAccountDevicesMetadataCallback callback);
- void loadFastPairEligibleAccounts(in FastPairEligibleAccountsRequestParcel request,
- in IFastPairEligibleAccountsCallback callback);
- void manageFastPairAccount(in FastPairManageAccountRequestParcel request,
- in IFastPairManageAccountCallback callback);
- void manageFastPairAccountDevice(in FastPairManageAccountDeviceRequestParcel request,
- in IFastPairManageAccountDeviceCallback callback);
-}
diff --git a/nearby/framework/java/android/nearby/aidl/IFastPairEligibleAccountsCallback.aidl b/nearby/framework/java/android/nearby/aidl/IFastPairEligibleAccountsCallback.aidl
deleted file mode 100644
index 9990014d405af74e72e2c144fc184bda986d3df3..0000000000000000000000000000000000000000
--- a/nearby/framework/java/android/nearby/aidl/IFastPairEligibleAccountsCallback.aidl
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright (C) 2021 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package android.nearby.aidl;
-
-import android.accounts.Account;
-import android.nearby.aidl.FastPairEligibleAccountParcel;
-
-/**
- * Provides callback interface for OEMs to return FastPair Eligible accounts.
- *
- * {@hide}
- */
-interface IFastPairEligibleAccountsCallback {
- void onFastPairEligibleAccountsReceived(in FastPairEligibleAccountParcel[] accounts);
- void onError(int code, String message);
- }
\ No newline at end of file
diff --git a/nearby/framework/java/android/nearby/aidl/IFastPairManageAccountCallback.aidl b/nearby/framework/java/android/nearby/aidl/IFastPairManageAccountCallback.aidl
deleted file mode 100644
index 6b4aaee0b64b07209d6062700543c35fb84b44c3..0000000000000000000000000000000000000000
--- a/nearby/framework/java/android/nearby/aidl/IFastPairManageAccountCallback.aidl
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (C) 2021 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package android.nearby.aidl;
-
-/**
- * Provides callback interface to send response for account management request.
- *
- * {@hide}
- */
-interface IFastPairManageAccountCallback {
- void onSuccess();
- void onError(int code, String message);
-}
\ No newline at end of file
diff --git a/nearby/framework/java/android/nearby/aidl/IFastPairManageAccountDeviceCallback.aidl b/nearby/framework/java/android/nearby/aidl/IFastPairManageAccountDeviceCallback.aidl
deleted file mode 100644
index bffc533e53db2f436576b2363318711ccf1d0504..0000000000000000000000000000000000000000
--- a/nearby/framework/java/android/nearby/aidl/IFastPairManageAccountDeviceCallback.aidl
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright (C) 2021 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package android.nearby.aidl;
-
-/**
- * Provides callback interface to send response for account-device mapping
- * management request.
- *
- * {@hide}
- */
-interface IFastPairManageAccountDeviceCallback {
- void onSuccess();
- void onError(int code, String message);
-}
\ No newline at end of file
diff --git a/nearby/framework/java/android/nearby/aidl/IFastPairStatusCallback.aidl b/nearby/framework/java/android/nearby/aidl/IFastPairStatusCallback.aidl
deleted file mode 100644
index d844c06f4041282fa590d475f203cac33708c06a..0000000000000000000000000000000000000000
--- a/nearby/framework/java/android/nearby/aidl/IFastPairStatusCallback.aidl
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2022, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.nearby.aidl;
-
-import android.nearby.FastPairDevice;
-import android.nearby.PairStatusMetadata;
-
-/**
- *
- * Provides callbacks for Fast Pair foreground activity to learn about paring status from backend.
- *
- * {@hide}
- */
-interface IFastPairStatusCallback {
-
- /** Reports a pair status related metadata associated with a {@link FastPairDevice} */
- void onPairUpdate(in FastPairDevice fastPairDevice, in PairStatusMetadata pairStatusMetadata);
-}
diff --git a/nearby/framework/java/android/nearby/aidl/IFastPairUiService.aidl b/nearby/framework/java/android/nearby/aidl/IFastPairUiService.aidl
deleted file mode 100644
index 9200a9d25440e1e2e90e0bb78f5f5e54c5a6259c..0000000000000000000000000000000000000000
--- a/nearby/framework/java/android/nearby/aidl/IFastPairUiService.aidl
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2022, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.nearby.aidl;
-
-import android.nearby.aidl.IFastPairStatusCallback;
-import android.nearby.FastPairDevice;
-
-/**
- * 0p API for controlling Fast Pair. Used to talk between foreground activities
- * and background services.
- *
- * {@hide}
- */
-interface IFastPairUiService {
-
- void registerCallback(in IFastPairStatusCallback fastPairStatusCallback);
-
- void unregisterCallback(in IFastPairStatusCallback fastPairStatusCallback);
-
- void connect(in FastPairDevice fastPairDevice);
-
- void cancel(in FastPairDevice fastPairDevice);
-}
\ No newline at end of file
diff --git a/nearby/halfsheet/Android.bp b/nearby/halfsheet/Android.bp
deleted file mode 100644
index 8011dc64e3d0a37a0991a7b713a7b1abe01afc8f..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/Android.bp
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright (C) 2021 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-android_app {
- name: "HalfSheetUX",
- defaults: ["platform_app_defaults"],
- srcs: ["src/**/*.java"],
- sdk_version: "module_current",
- // This is included in tethering apex, which uses min SDK 30
- min_sdk_version: "30",
- updatable: true,
- certificate: ":com.android.nearby.halfsheetcertificate",
- libs: [
- "framework-bluetooth",
- "framework-connectivity-t.impl",
- "nearby-service-string",
- ],
- static_libs: [
- "androidx.annotation_annotation",
- "androidx.fragment_fragment",
- "androidx-constraintlayout_constraintlayout",
- "androidx.localbroadcastmanager_localbroadcastmanager",
- "androidx.core_core",
- "androidx.appcompat_appcompat",
- "androidx.recyclerview_recyclerview",
- "androidx.lifecycle_lifecycle-runtime",
- "androidx.lifecycle_lifecycle-extensions",
- "com.google.android.material_material",
- "fast-pair-lite-protos",
- ],
- manifest: "AndroidManifest.xml",
- jarjar_rules: ":nearby-jarjar-rules",
- apex_available: ["com.android.tethering",],
- lint: { strict_updatability_linting: true }
-}
-
-android_app_certificate {
- name: "com.android.nearby.halfsheetcertificate",
- certificate: "apk-certs/com.android.nearby.halfsheet"
-}
diff --git a/nearby/halfsheet/AndroidManifest.xml b/nearby/halfsheet/AndroidManifest.xml
deleted file mode 100644
index 22987fb2a0e0533d1fbe11fe629b34d3896abb8d..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/AndroidManifest.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/nearby/halfsheet/apk-certs/com.android.nearby.halfsheet.pk8 b/nearby/halfsheet/apk-certs/com.android.nearby.halfsheet.pk8
deleted file mode 100644
index 187d51e6754399d45cb90c805151ef495a92f30d..0000000000000000000000000000000000000000
Binary files a/nearby/halfsheet/apk-certs/com.android.nearby.halfsheet.pk8 and /dev/null differ
diff --git a/nearby/halfsheet/apk-certs/com.android.nearby.halfsheet.x509.pem b/nearby/halfsheet/apk-certs/com.android.nearby.halfsheet.x509.pem
deleted file mode 100644
index 440c524a7f90a9dc8e317badfb0cc34fa2861870..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/apk-certs/com.android.nearby.halfsheet.x509.pem
+++ /dev/null
@@ -1,34 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIF6zCCA9OgAwIBAgIUU5ATKevcNA5ZSurwgwGenwrr4c4wDQYJKoZIhvcNAQEL
-BQAwgYMxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMQwwCgYDVQQH
-DANNVFYxDzANBgNVBAoMBkdvb2dsZTEPMA0GA1UECwwGbmVhcmJ5MQswCQYDVQQD
-DAJ3czEiMCAGCSqGSIb3DQEJARYTd2VpY2VzdW5AZ29vZ2xlLmNvbTAgFw0yMTEy
-MDgwMTMxMzFaGA80NzU5MTEwNDAxMzEzMVowgYMxCzAJBgNVBAYTAlVTMRMwEQYD
-VQQIDApDYWxpZm9ybmlhMQwwCgYDVQQHDANNVFYxDzANBgNVBAoMBkdvb2dsZTEP
-MA0GA1UECwwGbmVhcmJ5MQswCQYDVQQDDAJ3czEiMCAGCSqGSIb3DQEJARYTd2Vp
-Y2VzdW5AZ29vZ2xlLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB
-AO0JW1YZ5bKHZG5B9eputz3kGREmXcWZ97dg/ODDs3+op4ulBmgaYeo5yeCy29GI
-Sjgxo4G+9fNZ7Fejrk5/LLWovAoRvVxnkRxCkTfp15jZpKNnZjT2iTRLXzNz2O04
-cC0jB81mu5vJ9a8pt+EQkuSwjDMiUi6q4Sf6IRxtTCd5a1yn9eHf1y2BbCmU+Eys
-bs97HJl9PgMCp7hP+dYDxEtNTAESg5IpJ1i7uINgPNl8d0tvJ9rOEdy0IcdeGwt/
-t0L9fIoRCePttH+idKIyDjcNyp9WtX2/wZKlsGap83rGzLdL2PI4DYJ2Ytmy8W3a
-9qFJNrhl3Q3BYgPlcCg9qQOIKq6ZJgFFH3snVDKvtSFd8b9ofK7UzD5g2SllTqDA
-4YvrdK4GETQunSjG7AC/2PpvN/FdhHm7pBi0fkgwykMh35gv0h8mmb6pBISYgr85
-+GMBilNiNJ4G6j3cdOa72pvfDW5qn5dn5ks8cIgW2X1uF/GT8rR6Mb2rwhjY9eXk
-TaP0RykyzheMY/7dWeA/PdN3uMCEJEt72ZakDIswgQVPCIw8KQPIf6pl0d5hcLSV
-QzhqBaXudseVg0QlZ86iaobpZvCrW0KqQmMU5GVhEtDc2sPe5e+TCmUC/H+vo8F8
-1UYu3MJaBcpePFlgIsLhW0niUTfCq2FiNrPykOJT7U9NAgMBAAGjUzBRMB0GA1Ud
-DgQWBBQKSepRcKTv9hr8mmKjYCL7NeG2izAfBgNVHSMEGDAWgBQKSepRcKTv9hr8
-mmKjYCL7NeG2izAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4ICAQC/
-BoItafzvjYPzENY16BIkgRqJVU7IosWxGLczzg19NFu6HPa54alqkawp7RI1ZNVH
-bJjQma5ap0L+Y06/peIU9rvEtfbCkkYJwvIaSRlTlzrNwNEcj3yJMmGTr/wfIzq8
-PN1t0hihnqI8ZguOPC+sV6ARoC+ygkwaLU1oPbVvOGz9WplvSokE1mvtqKAyuDoL
-LZfWwbhxRAgwgCIEz6cPfEcgg3Xzc+L4OzmNhTTc7GNOAtvvW7Zqc2Lohb8nQMNw
-uY65yiHPNmjmc+xLHZk3jQg82tKv792JJRkVXPsIfQV087IzxFFjjvKy82rVfeaN
-F9g2EpUvdjtm8zx7K5tiDv9Es/Up7oOnoB5baLgnMAEVMTZY+4k/6BfVM5CVUu+H
-AO1yh2yeNWbzY8B+zxRef3C2Ax68lJHFyz8J1pfrGpWxML3rDmWiVDMtEk73t3g+
-lcyLYo7OW+iBn6BODRcINO4R640oyMjFz2wPSPAsU0Zj/MbgC6iaS+goS3QnyPQS
-O3hKWfwqQuA7BZ0la1n+plKH5PKxQESAbd37arzCsgQuktl33ONiwYOt6eUyHl/S
-E3ZdldkmGm9z0mcBYG9NczDBSYmtuZOGjEzIRqI5GFD2WixE+dqTzVP/kyBd4BLc
-OTmBynN/8D/qdUZNrT+tgs+mH/I2SsKYW9Zymwf7Qw==
------END CERTIFICATE-----
diff --git a/nearby/halfsheet/apk-certs/key.pem b/nearby/halfsheet/apk-certs/key.pem
deleted file mode 100644
index e9f4288aa08836c944505ea3486a7b198854a674..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/apk-certs/key.pem
+++ /dev/null
@@ -1,52 +0,0 @@
------BEGIN PRIVATE KEY-----
-MIIJQgIBADANBgkqhkiG9w0BAQEFAASCCSwwggkoAgEAAoICAQDtCVtWGeWyh2Ru
-QfXqbrc95BkRJl3Fmfe3YPzgw7N/qKeLpQZoGmHqOcngstvRiEo4MaOBvvXzWexX
-o65Ofyy1qLwKEb1cZ5EcQpE36deY2aSjZ2Y09ok0S18zc9jtOHAtIwfNZrubyfWv
-KbfhEJLksIwzIlIuquEn+iEcbUwneWtcp/Xh39ctgWwplPhMrG7PexyZfT4DAqe4
-T/nWA8RLTUwBEoOSKSdYu7iDYDzZfHdLbyfazhHctCHHXhsLf7dC/XyKEQnj7bR/
-onSiMg43DcqfVrV9v8GSpbBmqfN6xsy3S9jyOA2CdmLZsvFt2vahSTa4Zd0NwWID
-5XAoPakDiCqumSYBRR97J1Qyr7UhXfG/aHyu1Mw+YNkpZU6gwOGL63SuBhE0Lp0o
-xuwAv9j6bzfxXYR5u6QYtH5IMMpDId+YL9IfJpm+qQSEmIK/OfhjAYpTYjSeBuo9
-3HTmu9qb3w1uap+XZ+ZLPHCIFtl9bhfxk/K0ejG9q8IY2PXl5E2j9EcpMs4XjGP+
-3VngPz3Td7jAhCRLe9mWpAyLMIEFTwiMPCkDyH+qZdHeYXC0lUM4agWl7nbHlYNE
-JWfOomqG6Wbwq1tCqkJjFORlYRLQ3NrD3uXvkwplAvx/r6PBfNVGLtzCWgXKXjxZ
-YCLC4VtJ4lE3wqthYjaz8pDiU+1PTQIDAQABAoICAQCt4R5CM+8enlka1IIbvann
-2cpVnUpOaNqhh6EZFBY5gDOfqafgd/H5yvh/P1UnCI5BWJBz3ew33nAT/fsglAPt
-ImEGFetNvJ9jFqXGWWCRPJ6cS35bPbp6RQwKB2JK6grH4ZmYoFLhPi5elwDPNcQ7
-xBKkc/nLSAiwtbjSTI7/qf8K0h752aTUOctpWWEnhZon00ywf4Ic3TbBatF/n/W/
-s20coEMp1cyKN/JrVQ5uD/LGwDyBModB2lWpFSxLrB14I9DWyxbxP28X7ckXLhbl
-ZdWMOyQZoa/S7n5PYT49g1Wq5BW54UpvuH5c6fpWtrgSqk1cyUR2EbTf3NAAhPLU
-PgPK8wbFMcMB3TpQDXl7USA7QX5wSv22OfhivPsHQ9szGM0f84mK0PhXYPWBiNUY
-Y8rrIjOijB4eFGDFnTIMTofAb07NxRThci710BYUqgBVTBG5N+avIesjwkikMjOI
-PwYukKSQSw/Tqxy5Z9l22xksGynBZFjEFs/WT5pDczPAktA4xW3CGxjkMsIYaOBs
-OCEujqc5+mHSywYvy8aN+nA+yPucJP5e5pLZ1qaU0tqyakCx8XeeOyP6Wfm3UAAV
-AYelBRcWcJxM51w4o5UnUnpBD+Uxiz1sRVlqa9bLJjP4M+wJNL+WaIn9D6WhPOvl
-+naDC+p29ou2JzyKFDsOQQKCAQEA+Jalm+xAAPc+t/gCdAqEDo0NMA2/NG8m9BRc
-CVZRRaWVyGPeg5ziT/7caGwy2jpOZEjK0OOTCAqF+sJRDj6DDIw7nDrlxNyaXnCF
-gguQHFIYaHcjKGTs5l0vgL3H7pMFHN2qVynf4xrTuBXyT1GJ4vdWKAJbooa02c8W
-XI2fjwZ7Y8wSWrm1tn3oTTBR3N6o1GyPY6/TrL0mhpWwgx5eJeLl3GuUxOhXY5R9
-y48ziS97Dqdq75MxUOHickofCNcm7p+jA8Hg+SxLMR/kUFsXOxawmvsBqdL1XzU5
-LTS7xAEY9iMuBcO6yIxcxqBx96idjsPXx1lgARo1CpaZYCzgPQKCAQEA9BqKMN/Y
-o+T+ac99St8x3TYkk5lkvLVqlPw+EQhEqrm9EEBPntxWM5FEIpPVmFm7taGTgPfN
-KKaaNxX5XyK9B2v1QqN7XrX0nF4+6x7ao64fdpRUParIuBVctqzQWWthme66eHrf
-L86T/tkt3o/7p+Hd4Z9UT3FaAew1ggWr00xz5PJ/4b3f3mRmtNmgeTYskWMxOpSj
-bEenom4Row7sfLNeXNSWDGlzJ/lf6svvbVM2X5h2uFsxlt/Frq9ooTA3wwhnbd1i
-cFifDQ6cxF5mBpz/V/hnlHVfuXlknEZa9EQXHNo/aC9y+bR+ai05FJyK/WgqleW8
-5PBmoTReWA2MUQKCAQAnnnLkh+GnhcBEN83ESszDOO3KI9a+d5yguAH3Jv+q9voJ
-Rwl2tnFHSJo+NkhgiXxm9UcFxc9wL6Us0v1yJLpkLJFvk9984Z/kv1A36rncGaV0
-ONCspnEvQdjJTvXnax0cfaOhYrYhDuyBYVYOGDO+rabYl4+dNpTqRdwNgjDU7baK
-sEKYnRJ99FEqxDG33vDPckHkJGi7FiZmusK4EwX0SdZSq/6450LORyNJZxhSm/Oj
-4UDkz/PDLU0W5ANQOGInE+A6QBMoA0w0lx2fRPVN4I7jFHAubcXXl7b2InpugbJF
-wFOcbZZ+UgiTS4z+aKw7zbC9P9xSMKgVeO0W6/ANAoIBABe0LA8q7YKczgfAWk5W
-9iShCVQ75QheJYdqJyzIPMLHXpChbhnjE4vWY2NoL6mnrQ6qLgSsC4QTCY6n15th
-aDG8Tgi2j1hXGvXEQR/b0ydp1SxSowuJ9gvKJ0Kl7WWBg+zKvdjNNbcSvFRXCpk+
-KhXXXRB3xFwiibb+FQQXQOQ33FkzIy/snDygS0jsiSS8Gf/UPgeOP4BYRPME9Tl8
-TYKeeF9TVW7HHqOXF7VZMFrRZcpKp9ynHl2kRTH9Xo+oewG5YzHL+a8nK+q8rIR1
-Fjs2K6WDPauw6ia8nwR94H8vzX7Dwrx/Pw74c/4jfhN+UBDjeJ8tu/YPUif9SdwL
-FMECggEALdCGKfQ4vPmqI6UdfVB5hdCPoM6tUsI2yrXFvlHjSGVanC/IG9x2mpRb
-4odamLYx4G4NjP1IJSY08LFT9VhLZtRM1W3fGeboW12LTEVNrI3lRBU84rAQ1ced
-l6/DvTKJjhfwTxb/W7sqmZY5hF3QuNxs67Z8x0pe4b58musa0qFCs4Sa8qTNZKRW
-fIbxIKuvu1HSNOKkZLu6Gq8km+XIlVAaSVA03Tt+EK74MFL6+pcd7/VkS00MAYUC
-gS4ic+QFzCl5P8zl/GoX8iUFsRZQCSJkZ75VwO13pEupVwCAW8WWJO83U4jBsnJs
-ayrX7pbsnW6jsNYBUlck+RYVYkVkxA==
------END PRIVATE KEY-----
diff --git a/nearby/halfsheet/res/anim/fast_pair_bottom_sheet_enter.xml b/nearby/halfsheet/res/anim/fast_pair_bottom_sheet_enter.xml
deleted file mode 100644
index 098dccbf503d2ecd4092be40adabff3bad328e0f..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/anim/fast_pair_bottom_sheet_enter.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
diff --git a/nearby/halfsheet/res/anim/fast_pair_bottom_sheet_exit.xml b/nearby/halfsheet/res/anim/fast_pair_bottom_sheet_exit.xml
deleted file mode 100644
index 1cf7401f76a33f027b8c2c5cbb82ed50bd95cde6..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/anim/fast_pair_bottom_sheet_exit.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
diff --git a/nearby/halfsheet/res/anim/fast_pair_half_sheet_slide_in.xml b/nearby/halfsheet/res/anim/fast_pair_half_sheet_slide_in.xml
deleted file mode 100644
index 9a51ddbe40130f417348607e8099875f89c33796..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/anim/fast_pair_half_sheet_slide_in.xml
+++ /dev/null
@@ -1,14 +0,0 @@
-
-
-
-
-
-
diff --git a/nearby/halfsheet/res/anim/fast_pair_half_sheet_slide_out.xml b/nearby/halfsheet/res/anim/fast_pair_half_sheet_slide_out.xml
deleted file mode 100644
index c589482c33aae451b3e5a99cf7ac58da40dd5f5d..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/anim/fast_pair_half_sheet_slide_out.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
-
-
-
-
-
-
diff --git a/nearby/halfsheet/res/drawable/fast_pair_ic_info.xml b/nearby/halfsheet/res/drawable/fast_pair_ic_info.xml
deleted file mode 100644
index 7d61d1c970c0dbeddd49081ae8be03f2844e37fc..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/drawable/fast_pair_ic_info.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/nearby/halfsheet/res/drawable/fastpair_outline.xml b/nearby/halfsheet/res/drawable/fastpair_outline.xml
deleted file mode 100644
index 6765e1194c97fae256e48b4ae8e5eeb67eee19db..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/drawable/fastpair_outline.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
diff --git a/nearby/halfsheet/res/drawable/half_sheet_bg.xml b/nearby/halfsheet/res/drawable/half_sheet_bg.xml
deleted file mode 100644
index 7e7d8ddaeb33d026f7f02984f3d47151a0b02179..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/drawable/half_sheet_bg.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
-
-
diff --git a/nearby/halfsheet/res/layout/fast_pair_device_pairing_fragment.xml b/nearby/halfsheet/res/layout/fast_pair_device_pairing_fragment.xml
deleted file mode 100644
index 7fbe229cfde85c9a74a938f04a020b47d39ad690..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/layout/fast_pair_device_pairing_fragment.xml
+++ /dev/null
@@ -1,139 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/nearby/halfsheet/res/layout/fast_pair_half_sheet.xml b/nearby/halfsheet/res/layout/fast_pair_half_sheet.xml
deleted file mode 100644
index 705aa1b15804a16b2145f9a0480e29958e8e9df5..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/layout/fast_pair_half_sheet.xml
+++ /dev/null
@@ -1,66 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/nearby/halfsheet/res/layout/fast_pair_heads_up_notification.xml b/nearby/halfsheet/res/layout/fast_pair_heads_up_notification.xml
deleted file mode 100644
index 11b83434013b4f5e562a61d685eeaa8ed3671343..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/layout/fast_pair_heads_up_notification.xml
+++ /dev/null
@@ -1,83 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/nearby/halfsheet/res/layout/fast_pair_heads_up_notification_large_image.xml b/nearby/halfsheet/res/layout/fast_pair_heads_up_notification_large_image.xml
deleted file mode 100644
index dd289477eab92ce82271cf78ab57573cc3270c16..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/layout/fast_pair_heads_up_notification_large_image.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-
diff --git a/nearby/halfsheet/res/layout/fast_pair_heads_up_notification_small_image.xml b/nearby/halfsheet/res/layout/fast_pair_heads_up_notification_small_image.xml
deleted file mode 100644
index ee1d89f59bdf374cdd45de222be6d734e7432263..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/layout/fast_pair_heads_up_notification_small_image.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-
diff --git a/nearby/halfsheet/res/values-af/strings.xml b/nearby/halfsheet/res/values-af/strings.xml
deleted file mode 100644
index 7333e63a2f55fd606f93442f98ff8c4ebc3d9013..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/values-af/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
- "Begin tans opstelling …"
- "Stel toestel op"
- "Toestel is gekoppel"
- "Kon nie koppel nie"
- "Klaar"
- "Stoor"
- "Koppel"
- "Stel op"
- "Instellings"
-
diff --git a/nearby/halfsheet/res/values-am/strings.xml b/nearby/halfsheet/res/values-am/strings.xml
deleted file mode 100644
index da3b14494b8b578f73c254d09cb7c8e0f25f1944..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/values-am/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
- "ማዋቀርን በመጀመር ላይ…"
- "መሣሪያ አዋቅር"
- "መሣሪያ ተገናኝቷል"
- "መገናኘት አልተቻለም"
- "ተጠናቅቋል"
- "አስቀምጥ"
- "አገናኝ"
- "አዋቅር"
- "ቅንብሮች"
-
diff --git a/nearby/halfsheet/res/values-ar/strings.xml b/nearby/halfsheet/res/values-ar/strings.xml
deleted file mode 100644
index d0bfce4c3ba5379ad0895639774b9ed6beb05cd7..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/values-ar/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
- "جارٍ الإعداد…"
- "إعداد جهاز"
- "تمّ إقران الجهاز"
- "تعذّر الربط"
- "تم"
- "حفظ"
- "ربط"
- "إعداد"
- "الإعدادات"
-
diff --git a/nearby/halfsheet/res/values-as/strings.xml b/nearby/halfsheet/res/values-as/strings.xml
deleted file mode 100644
index 8ff49462b4a9085f8af51e17fcfed2569b66ff11..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/values-as/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
- "ছেটআপ আৰম্ভ কৰি থকা হৈছে…"
- "ডিভাইচ ছেট আপ কৰক"
- "ডিভাইচ সংযোগ কৰা হ’ল"
- "সংযোগ কৰিব পৰা নগ’ল"
- "হ’ল"
- "ছেভ কৰক"
- "সংযোগ কৰক"
- "ছেট আপ কৰক"
- "ছেটিং"
-
diff --git a/nearby/halfsheet/res/values-az/strings.xml b/nearby/halfsheet/res/values-az/strings.xml
deleted file mode 100644
index af499ef6f9be6f7a017f3e55f175b85ff47130c2..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/values-az/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
- "Ayarlama başladılır…"
- "Cihazı quraşdırın"
- "Cihaz qoşulub"
- "Qoşulmaq mümkün olmadı"
- "Oldu"
- "Saxlayın"
- "Qoşun"
- "Ayarlayın"
- "Ayarlar"
-
diff --git a/nearby/halfsheet/res/values-b+sr+Latn/strings.xml b/nearby/halfsheet/res/values-b+sr+Latn/strings.xml
deleted file mode 100644
index eea6b647551c28d50a817515b82e3730484ee3a1..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/values-b+sr+Latn/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
- "Podešavanje se pokreće…"
- "Podesite uređaj"
- "Uređaj je povezan"
- "Povezivanje nije uspelo"
- "Gotovo"
- "Sačuvaj"
- "Poveži"
- "Podesi"
- "Podešavanja"
-
diff --git a/nearby/halfsheet/res/values-be/strings.xml b/nearby/halfsheet/res/values-be/strings.xml
deleted file mode 100644
index a5c1ef6b7d1e7023b1bc91e4a0661f9b49cb47f5..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/values-be/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
- "Пачынаецца наладжванне…"
- "Наладзьце прыладу"
- "Прылада падключана"
- "Не ўдалося падключыцца"
- "Гатова"
- "Захаваць"
- "Падключыць"
- "Наладзіць"
- "Налады"
-
diff --git a/nearby/halfsheet/res/values-bg/strings.xml b/nearby/halfsheet/res/values-bg/strings.xml
deleted file mode 100644
index 0ee7aef11f30fad0b78dbffc229126c266b31ade..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/values-bg/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
- "Настройването се стартира…"
- "Настройване на устройството"
- "Устройството е свързано"
- "Свързването не бе успешно"
- "Готово"
- "Запазване"
- "Свързване"
- "Настройване"
- "Настройки"
-
diff --git a/nearby/halfsheet/res/values-bn/strings.xml b/nearby/halfsheet/res/values-bn/strings.xml
deleted file mode 100644
index 484e35b5ab73f45d3e4bd8ddc3e05343a6e8358b..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/values-bn/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
- "সেট-আপ করা শুরু হচ্ছে…"
- "ডিভাইস সেট-আপ করুন"
- "ডিভাইস কানেক্ট হয়েছে"
- "কানেক্ট করা যায়নি"
- "হয়ে গেছে"
- "সেভ করুন"
- "কানেক্ট করুন"
- "সেট-আপ করুন"
- "সেটিংস"
-
diff --git a/nearby/halfsheet/res/values-bs/strings.xml b/nearby/halfsheet/res/values-bs/strings.xml
deleted file mode 100644
index 2fc8644b96efd1a7e8158f310e771c808ee4c6fd..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/values-bs/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
- "Pokretanje postavljanja…"
- "Postavi uređaj"
- "Uređaj je povezan"
- "Povezivanje nije uspjelo"
- "Gotovo"
- "Sačuvaj"
- "Poveži"
- "Postavi"
- "Postavke"
-
diff --git a/nearby/halfsheet/res/values-ca/strings.xml b/nearby/halfsheet/res/values-ca/strings.xml
deleted file mode 100644
index 8912792499f52a9be4f08e31e8cce8719083dc93..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/values-ca/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
- "Iniciant la configuració…"
- "Configura el dispositiu"
- "El dispositiu s\'ha connectat"
- "No s\'ha pogut connectar"
- "Fet"
- "Desa"
- "Connecta"
- "Configura"
- "Configuració"
-
diff --git a/nearby/halfsheet/res/values-cs/strings.xml b/nearby/halfsheet/res/values-cs/strings.xml
deleted file mode 100644
index 7e7ea3cc4faea9a1c6766b1afc22234764a3fc16..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/values-cs/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
- "Zahajování nastavení…"
- "Nastavení zařízení"
- "Zařízení je připojeno"
- "Nelze se připojit"
- "Hotovo"
- "Uložit"
- "Připojit"
- "Nastavit"
- "Nastavení"
-
diff --git a/nearby/halfsheet/res/values-da/strings.xml b/nearby/halfsheet/res/values-da/strings.xml
deleted file mode 100644
index 1d937e2963325e309a97da236855e1a7e04839a6..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/values-da/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
- "Begynder konfiguration…"
- "Konfigurer enhed"
- "Enheden er forbundet"
- "Forbindelsen kan ikke oprettes"
- "Luk"
- "Gem"
- "Opret forbindelse"
- "Konfigurer"
- "Indstillinger"
-
diff --git a/nearby/halfsheet/res/values-de/strings.xml b/nearby/halfsheet/res/values-de/strings.xml
deleted file mode 100644
index 9186a4473d772fd6769dabb26d9dcf1197673699..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/values-de/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
- "Einrichtung wird gestartet..."
- "Gerät einrichten"
- "Gerät verbunden"
- "Verbindung nicht möglich"
- "Fertig"
- "Speichern"
- "Verbinden"
- "Einrichten"
- "Einstellungen"
-
diff --git a/nearby/halfsheet/res/values-el/strings.xml b/nearby/halfsheet/res/values-el/strings.xml
deleted file mode 100644
index 3e18a93a60abf6ddcff4bad49db98277eb841668..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/values-el/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
- "Έναρξη ρύθμισης…"
- "Ρύθμιση συσκευής"
- "Η συσκευή συνδέθηκε"
- "Αδυναμία σύνδεσης"
- "Τέλος"
- "Αποθήκευση"
- "Σύνδεση"
- "Ρύθμιση"
- "Ρυθμίσεις"
-
diff --git a/nearby/halfsheet/res/values-en-rAU/strings.xml b/nearby/halfsheet/res/values-en-rAU/strings.xml
deleted file mode 100644
index d4ed675b30f83938d31a5fceb5c889742e4a0703..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/values-en-rAU/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
- "Starting setup…"
- "Set up device"
- "Device connected"
- "Couldn\'t connect"
- "Done"
- "Save"
- "Connect"
- "Set up"
- "Settings"
-
diff --git a/nearby/halfsheet/res/values-en-rCA/strings.xml b/nearby/halfsheet/res/values-en-rCA/strings.xml
deleted file mode 100644
index 6094199209761d2ac6e220f059a6656580258f1f..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/values-en-rCA/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
- "Starting Setup…"
- "Set up device"
- "Device connected"
- "Couldn\'t connect"
- "Done"
- "Save"
- "Connect"
- "Set up"
- "Settings"
-
diff --git a/nearby/halfsheet/res/values-en-rGB/strings.xml b/nearby/halfsheet/res/values-en-rGB/strings.xml
deleted file mode 100644
index d4ed675b30f83938d31a5fceb5c889742e4a0703..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/values-en-rGB/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
- "Starting setup…"
- "Set up device"
- "Device connected"
- "Couldn\'t connect"
- "Done"
- "Save"
- "Connect"
- "Set up"
- "Settings"
-
diff --git a/nearby/halfsheet/res/values-en-rIN/strings.xml b/nearby/halfsheet/res/values-en-rIN/strings.xml
deleted file mode 100644
index d4ed675b30f83938d31a5fceb5c889742e4a0703..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/values-en-rIN/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
- "Starting setup…"
- "Set up device"
- "Device connected"
- "Couldn\'t connect"
- "Done"
- "Save"
- "Connect"
- "Set up"
- "Settings"
-
diff --git a/nearby/halfsheet/res/values-en-rXC/strings.xml b/nearby/halfsheet/res/values-en-rXC/strings.xml
deleted file mode 100644
index 460cc1bbdb78b4f9fb85962d2e33056d6de80409..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/values-en-rXC/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
- "Starting Setup…"
- "Set up device"
- "Device connected"
- "Couldn\'t connect"
- "Done"
- "Save"
- "Connect"
- "Set up"
- "Settings"
-
diff --git a/nearby/halfsheet/res/values-es-rUS/strings.xml b/nearby/halfsheet/res/values-es-rUS/strings.xml
deleted file mode 100644
index d8fb2836d51ea77ef44a04346bbcd7f227f08896..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/values-es-rUS/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
- "Iniciando la configuración…"
- "Configuración del dispositivo"
- "Se conectó el dispositivo"
- "No se pudo establecer conexión"
- "Listo"
- "Guardar"
- "Conectar"
- "Configurar"
- "Configuración"
-
diff --git a/nearby/halfsheet/res/values-es/strings.xml b/nearby/halfsheet/res/values-es/strings.xml
deleted file mode 100644
index 4b8340a2f74935f15113d10aa44968eedb3ea838..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/values-es/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
- "Iniciando configuración…"
- "Configurar el dispositivo"
- "Dispositivo conectado"
- "No se ha podido conectar"
- "Hecho"
- "Guardar"
- "Conectar"
- "Configurar"
- "Ajustes"
-
diff --git a/nearby/halfsheet/res/values-et/strings.xml b/nearby/halfsheet/res/values-et/strings.xml
deleted file mode 100644
index e6abc6453fd2a7c12aefc7031adb5647a6f603fc..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/values-et/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
- "Seadistuse käivitamine …"
- "Seadistage seade"
- "Seade on ühendatud"
- "Ühendamine ebaõnnestus"
- "Valmis"
- "Salvesta"
- "Ühenda"
- "Seadistamine"
- "Seaded"
-
diff --git a/nearby/halfsheet/res/values-eu/strings.xml b/nearby/halfsheet/res/values-eu/strings.xml
deleted file mode 100644
index 4243fd55ac355e4ced392b5a62997d82edcc9968..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/values-eu/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
- "Konfigurazio-prozesua abiarazten…"
- "Konfiguratu gailua"
- "Konektatu da gailua"
- "Ezin izan da konektatu"
- "Eginda"
- "Gorde"
- "Konektatu"
- "Konfiguratu"
- "Ezarpenak"
-
diff --git a/nearby/halfsheet/res/values-fa/strings.xml b/nearby/halfsheet/res/values-fa/strings.xml
deleted file mode 100644
index 3585f9518d0c66f3561d1b32142d012caf7839ad..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/values-fa/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
- "درحال شروع راهاندازی…"
- "راهاندازی دستگاه"
- "دستگاه متصل شد"
- "متصل نشد"
- "تمام"
- "ذخیره"
- "متصل کردن"
- "راهاندازی"
- "تنظیمات"
-
diff --git a/nearby/halfsheet/res/values-fi/strings.xml b/nearby/halfsheet/res/values-fi/strings.xml
deleted file mode 100644
index e8d47de8782882cd67b8a79d1294c18609ba9083..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/values-fi/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
- "Aloitetaan käyttöönottoa…"
- "Määritä laite"
- "Laite on yhdistetty"
- "Ei yhteyttä"
- "Valmis"
- "Tallenna"
- "Yhdistä"
- "Ota käyttöön"
- "Asetukset"
-
diff --git a/nearby/halfsheet/res/values-fr-rCA/strings.xml b/nearby/halfsheet/res/values-fr-rCA/strings.xml
deleted file mode 100644
index 64dd107b8fc08fa62440a5550d8a9c9c8c1369e6..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/values-fr-rCA/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
- "Démarrage de la configuration…"
- "Configurer l\'appareil"
- "Appareil associé"
- "Impossible d\'associer"
- "OK"
- "Enregistrer"
- "Associer"
- "Configurer"
- "Paramètres"
-
diff --git a/nearby/halfsheet/res/values-fr/strings.xml b/nearby/halfsheet/res/values-fr/strings.xml
deleted file mode 100644
index 484c57bdea2a14580f5f446e96afe7d1dd17e860..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/values-fr/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
- "Début de la configuration…"
- "Configurer un appareil"
- "Appareil associé"
- "Impossible de se connecter"
- "OK"
- "Enregistrer"
- "Connecter"
- "Configurer"
- "Paramètres"
-
diff --git a/nearby/halfsheet/res/values-gl/strings.xml b/nearby/halfsheet/res/values-gl/strings.xml
deleted file mode 100644
index 30393ff8fcefd39403e3d1cb2027b5d265d42162..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/values-gl/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
- "Iniciando configuración…"
- "Configura o dispositivo"
- "Conectouse o dispositivo"
- "Non se puido conectar"
- "Feito"
- "Gardar"
- "Conectar"
- "Configurar"
- "Configuración"
-
diff --git a/nearby/halfsheet/res/values-gu/strings.xml b/nearby/halfsheet/res/values-gu/strings.xml
deleted file mode 100644
index 03b057d37ad375afa1d91162c98f957305ca1485..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/values-gu/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
- "સેટઅપ શરૂ કરી રહ્યાં છીએ…"
- "ડિવાઇસનું સેટઅપ કરો"
- "ડિવાઇસ કનેક્ટ કર્યું"
- "કનેક્ટ કરી શક્યા નથી"
- "થઈ ગયું"
- "સાચવો"
- "કનેક્ટ કરો"
- "સેટઅપ કરો"
- "સેટિંગ"
-
diff --git a/nearby/halfsheet/res/values-hi/strings.xml b/nearby/halfsheet/res/values-hi/strings.xml
deleted file mode 100644
index ecd420e3bf3e390d2d11f9eb8202223d7269c5f2..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/values-hi/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
- "सेट अप शुरू किया जा रहा है…"
- "डिवाइस सेट अप करें"
- "डिवाइस कनेक्ट हो गया"
- "कनेक्ट नहीं किया जा सका"
- "हो गया"
- "सेव करें"
- "कनेक्ट करें"
- "सेट अप करें"
- "सेटिंग"
-
diff --git a/nearby/halfsheet/res/values-hr/strings.xml b/nearby/halfsheet/res/values-hr/strings.xml
deleted file mode 100644
index 5a3de8f11c0a3d445acb8ee78f8e2af3f593a8f1..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/values-hr/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
- "Pokretanje postavljanja…"
- "Postavi uređaj"
- "Uređaj je povezan"
- "Povezivanje nije uspjelo"
- "Gotovo"
- "Spremi"
- "Poveži"
- "Postavi"
- "Postavke"
-
diff --git a/nearby/halfsheet/res/values-hu/strings.xml b/nearby/halfsheet/res/values-hu/strings.xml
deleted file mode 100644
index ba3d2e0b86e674c7770442e57c4aaa0d60341b30..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/values-hu/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
- "Beállítás megkezdése…"
- "Eszköz beállítása"
- "Eszköz csatlakoztatva"
- "Nem sikerült csatlakozni"
- "Kész"
- "Mentés"
- "Csatlakozás"
- "Beállítás"
- "Beállítások"
-
diff --git a/nearby/halfsheet/res/values-hy/strings.xml b/nearby/halfsheet/res/values-hy/strings.xml
deleted file mode 100644
index ecabd16c29ece6cc5ffb2f94d3640482ac15d017..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/values-hy/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
- "Կարգավորում…"
- "Կարգավորեք սարքը"
- "Սարքը զուգակցվեց"
- "Չհաջողվեց միանալ"
- "Պատրաստ է"
- "Պահել"
- "Միանալ"
- "Կարգավորել"
- "Կարգավորումներ"
-
diff --git a/nearby/halfsheet/res/values-in/strings.xml b/nearby/halfsheet/res/values-in/strings.xml
deleted file mode 100644
index dc777b2193c9d214ce1833c10cba684bb1b4c7f7..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/values-in/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
- "Memulai Penyiapan …"
- "Siapkan perangkat"
- "Perangkat terhubung"
- "Tidak dapat terhubung"
- "Selesai"
- "Simpan"
- "Hubungkan"
- "Siapkan"
- "Setelan"
-
diff --git a/nearby/halfsheet/res/values-is/strings.xml b/nearby/halfsheet/res/values-is/strings.xml
deleted file mode 100644
index ee094d9fe5aa2d7b4247cc9e4cb654a31fb6ba54..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/values-is/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
- "Ræsir uppsetningu…"
- "Uppsetning tækis"
- "Tækið er tengt"
- "Tenging mistókst"
- "Lokið"
- "Vista"
- "Tengja"
- "Setja upp"
- "Stillingar"
-
diff --git a/nearby/halfsheet/res/values-it/strings.xml b/nearby/halfsheet/res/values-it/strings.xml
deleted file mode 100644
index 700dd77b552605db380044c3dcb391432822dbb6..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/values-it/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
- "Avvio della configurazione…"
- "Configura dispositivo"
- "Dispositivo connesso"
- "Impossibile connettere"
- "Fine"
- "Salva"
- "Connetti"
- "Configura"
- "Impostazioni"
-
diff --git a/nearby/halfsheet/res/values-iw/strings.xml b/nearby/halfsheet/res/values-iw/strings.xml
deleted file mode 100644
index e6ff9b949c079436322a860ea77c69969bafc82a..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/values-iw/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
- "ההגדרה מתבצעת…"
- "הגדרת המכשיר"
- "המכשיר מחובר"
- "לא ניתן להתחבר"
- "סיום"
- "שמירה"
- "התחברות"
- "הגדרה"
- "הגדרות"
-
diff --git a/nearby/halfsheet/res/values-ja/strings.xml b/nearby/halfsheet/res/values-ja/strings.xml
deleted file mode 100644
index a429b7e5a704a1c970b67187639de6c6cf0e6b09..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/values-ja/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
- "セットアップを開始中…"
- "デバイスのセットアップ"
- "デバイス接続完了"
- "接続エラー"
- "完了"
- "保存"
- "接続"
- "セットアップ"
- "設定"
-
diff --git a/nearby/halfsheet/res/values-ka/strings.xml b/nearby/halfsheet/res/values-ka/strings.xml
deleted file mode 100644
index 4353ae9758fc44df32187fa9095c83b8ef79c963..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/values-ka/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
- "დაყენება იწყება…"
- "მოწყობილობის დაყენება"
- "მოწყობილობა დაკავშირებულია"
- "დაკავშირება ვერ მოხერხდა"
- "მზადაა"
- "შენახვა"
- "დაკავშირება"
- "დაყენება"
- "პარამეტრები"
-
diff --git a/nearby/halfsheet/res/values-kk/strings.xml b/nearby/halfsheet/res/values-kk/strings.xml
deleted file mode 100644
index 98d8073cdac8ecad6f01151c297a5689ca406649..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/values-kk/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
- "Реттеу басталуда…"
- "Құрылғыны реттеу"
- "Құрылғы байланыстырылды"
- "Қосылмады"
- "Дайын"
- "Сақтау"
- "Қосу"
- "Реттеу"
- "Параметрлер"
-
diff --git a/nearby/halfsheet/res/values-km/strings.xml b/nearby/halfsheet/res/values-km/strings.xml
deleted file mode 100644
index 85e39dbd8f0b8b6b1b6d2d5b71b42b799b6efebe..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/values-km/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
- "កំពុងចាប់ផ្ដើមរៀបចំ…"
- "រៀបចំឧបករណ៍"
- "បានភ្ជាប់ឧបករណ៍"
- "មិនអាចភ្ជាប់បានទេ"
- "រួចរាល់"
- "រក្សាទុក"
- "ភ្ជាប់"
- "រៀបចំ"
- "ការកំណត់"
-
diff --git a/nearby/halfsheet/res/values-kn/strings.xml b/nearby/halfsheet/res/values-kn/strings.xml
deleted file mode 100644
index fb62bb1d2dbbc4ce14f3b2790409fbb36ad1dda7..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/values-kn/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
- "ಸೆಟಪ್ ಪ್ರಾರಂಭಿಸಲಾಗುತ್ತಿದೆ…"
- "ಸಾಧನವನ್ನು ಸೆಟಪ್ ಮಾಡಿ"
- "ಸಾಧನವನ್ನು ಕನೆಕ್ಟ್ ಮಾಡಲಾಗಿದೆ"
- "ಕನೆಕ್ಟ್ ಮಾಡಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ"
- "ಮುಗಿದಿದೆ"
- "ಉಳಿಸಿ"
- "ಕನೆಕ್ಟ್ ಮಾಡಿ"
- "ಸೆಟಪ್ ಮಾಡಿ"
- "ಸೆಟ್ಟಿಂಗ್ಗಳು"
-
diff --git a/nearby/halfsheet/res/values-ko/strings.xml b/nearby/halfsheet/res/values-ko/strings.xml
deleted file mode 100644
index c94ff7650cc7939f0e5a5c47eeb1ceecd7a46f93..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/values-ko/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
- "설정을 시작하는 중…"
- "기기 설정"
- "기기 연결됨"
- "연결할 수 없음"
- "완료"
- "저장"
- "연결"
- "설정"
- "설정"
-
diff --git a/nearby/halfsheet/res/values-ky/strings.xml b/nearby/halfsheet/res/values-ky/strings.xml
deleted file mode 100644
index b0dfe2097cc2203470b7e2206b57f5395c6e027d..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/values-ky/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
- "Жөндөлүп баштады…"
- "Түзмөктү жөндөө"
- "Түзмөк туташты"
- "Туташпай койду"
- "Бүттү"
- "Сактоо"
- "Туташуу"
- "Жөндөө"
- "Параметрлер"
-
diff --git a/nearby/halfsheet/res/values-lo/strings.xml b/nearby/halfsheet/res/values-lo/strings.xml
deleted file mode 100644
index 9c945b247eff19667691b80044255957fb66c4b7..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/values-lo/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
- "ກຳລັງເລີ່ມການຕັ້ງຄ່າ…"
- "ຕັ້ງຄ່າອຸປະກອນ"
- "ເຊື່ອມຕໍ່ອຸປະກອນແລ້ວ"
- "ບໍ່ສາມາດເຊື່ອມຕໍ່ໄດ້"
- "ແລ້ວໆ"
- "ບັນທຶກ"
- "ເຊື່ອມຕໍ່"
- "ຕັ້ງຄ່າ"
- "ການຕັ້ງຄ່າ"
-
diff --git a/nearby/halfsheet/res/values-lt/strings.xml b/nearby/halfsheet/res/values-lt/strings.xml
deleted file mode 100644
index 5dbad0ad33cb0257ecc314e6f92b926dd6ace664..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/values-lt/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
- "Pradedama sąranka…"
- "Įrenginio nustatymas"
- "Įrenginys prijungtas"
- "Prisijungti nepavyko"
- "Atlikta"
- "Išsaugoti"
- "Prisijungti"
- "Nustatyti"
- "Nustatymai"
-
diff --git a/nearby/halfsheet/res/values-lv/strings.xml b/nearby/halfsheet/res/values-lv/strings.xml
deleted file mode 100644
index a9e1bf9c6f3d0a14ea1eeaa9dac9d3040fb84670..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/values-lv/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
- "Tiek sākta iestatīšana…"
- "Iestatiet ierīci"
- "Ierīce ir pievienota"
- "Nevarēja izveidot savienojumu"
- "Gatavs"
- "Saglabāt"
- "Izveidot savienojumu"
- "Iestatīt"
- "Iestatījumi"
-
diff --git a/nearby/halfsheet/res/values-mk/strings.xml b/nearby/halfsheet/res/values-mk/strings.xml
deleted file mode 100644
index e29dfa146b07cf1d9b450274c66efdd88a7aae35..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/values-mk/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
- "Се започнува со поставување…"
- "Поставете го уредот"
- "Уредот е поврзан"
- "Не може да се поврзе"
- "Готово"
- "Зачувај"
- "Поврзи"
- "Поставете"
- "Поставки"
-
diff --git a/nearby/halfsheet/res/values-ml/strings.xml b/nearby/halfsheet/res/values-ml/strings.xml
deleted file mode 100644
index cbc171bf17f7b09dd4ff10e0142e95c5c6a9a94d..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/values-ml/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
- "സജ്ജീകരിക്കൽ ആരംഭിക്കുന്നു…"
- "ഉപകരണം സജ്ജീകരിക്കുക"
- "ഉപകരണം കണക്റ്റ് ചെയ്തു"
- "കണക്റ്റ് ചെയ്യാനായില്ല"
- "പൂർത്തിയായി"
- "സംരക്ഷിക്കുക"
- "കണക്റ്റ് ചെയ്യുക"
- "സജ്ജീകരിക്കുക"
- "ക്രമീകരണം"
-
diff --git a/nearby/halfsheet/res/values-mn/strings.xml b/nearby/halfsheet/res/values-mn/strings.xml
deleted file mode 100644
index 6d21effb4a71c424b78231bec7205a29df5ffefc..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/values-mn/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
- "Тохируулгыг эхлүүлж байна…"
- "Төхөөрөмж тохируулах"
- "Төхөөрөмж холбогдсон"
- "Холбогдож чадсангүй"
- "Болсон"
- "Хадгалах"
- "Холбох"
- "Тохируулах"
- "Тохиргоо"
-
diff --git a/nearby/halfsheet/res/values-mr/strings.xml b/nearby/halfsheet/res/values-mr/strings.xml
deleted file mode 100644
index a3e1d7a843059387e7d653eda0396b413653a033..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/values-mr/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
- "सेटअप सुरू करत आहे…"
- "डिव्हाइस सेट करा"
- "डिव्हाइस कनेक्ट केले आहे"
- "कनेक्ट करता आले नाही"
- "पूर्ण झाले"
- "सेव्ह करा"
- "कनेक्ट करा"
- "सेट करा"
- "सेटिंग्ज"
-
diff --git a/nearby/halfsheet/res/values-ms/strings.xml b/nearby/halfsheet/res/values-ms/strings.xml
deleted file mode 100644
index 4835c1b335d6b54bd8dd7abd68f72946d1167869..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/values-ms/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
- "Memulakan Persediaan…"
- "Sediakan peranti"
- "Peranti disambungkan"
- "Tidak dapat menyambung"
- "Selesai"
- "Simpan"
- "Sambung"
- "Sediakan"
- "Tetapan"
-
diff --git a/nearby/halfsheet/res/values-my/strings.xml b/nearby/halfsheet/res/values-my/strings.xml
deleted file mode 100644
index 32c310508079b3824cb7717928de4316f2d9d209..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/values-my/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
- "စနစ်ထည့်သွင်းခြင်း စတင်နေသည်…"
- "စက်ကို စနစ်ထည့်သွင်းရန်"
- "စက်ကို ချိတ်ဆက်လိုက်ပြီ"
- "ချိတ်ဆက်၍မရပါ"
- "ပြီးပြီ"
- "သိမ်းရန်"
- "ချိတ်ဆက်ရန်"
- "စနစ်ထည့်သွင်းရန်"
- "ဆက်တင်များ"
-
diff --git a/nearby/halfsheet/res/values-nb/strings.xml b/nearby/halfsheet/res/values-nb/strings.xml
deleted file mode 100644
index 9d725659a16e1be1c261059d7e9e67854c24ceed..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/values-nb/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
- "Starter konfigureringen …"
- "Konfigurer enheten"
- "Enheten er tilkoblet"
- "Kunne ikke koble til"
- "Ferdig"
- "Lagre"
- "Koble til"
- "Konfigurer"
- "Innstillinger"
-
diff --git a/nearby/halfsheet/res/values-ne/strings.xml b/nearby/halfsheet/res/values-ne/strings.xml
deleted file mode 100644
index 1370412b1ede0f6b34e50e46a7196d8405c38004..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/values-ne/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
- "सेटअप प्रक्रिया सुरु गरिँदै छ…"
- "डिभाइस सेटअप गर्नुहोस्"
- "डिभाइस कनेक्ट गरियो"
- "कनेक्ट गर्न सकिएन"
- "सम्पन्न भयो"
- "सेभ गर्नुहोस्"
- "कनेक्ट गर्नुहोस्"
- "सेटअप गर्नुहोस्"
- "सेटिङ"
-
diff --git a/nearby/halfsheet/res/values-nl/strings.xml b/nearby/halfsheet/res/values-nl/strings.xml
deleted file mode 100644
index 4eb7624b57fcc5cf1f7b348c2a45d98a39fc3f83..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/values-nl/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
- "Instellen starten…"
- "Apparaat instellen"
- "Apparaat verbonden"
- "Kan geen verbinding maken"
- "Klaar"
- "Opslaan"
- "Verbinden"
- "Instellen"
- "Instellingen"
-
diff --git a/nearby/halfsheet/res/values-or/strings.xml b/nearby/halfsheet/res/values-or/strings.xml
deleted file mode 100644
index c5e8cfcc73647447be8cf9906730eaca743f42cb..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/values-or/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
- "ସେଟଅପ ଆରମ୍ଭ କରାଯାଉଛି…"
- "ଡିଭାଇସ ସେଟ ଅପ କରନ୍ତୁ"
- "ଡିଭାଇସ ସଂଯୁକ୍ତ ହୋଇଛି"
- "ସଂଯୋଗ କରାଯାଇପାରିଲା ନାହିଁ"
- "ହୋଇଗଲା"
- "ସେଭ କରନ୍ତୁ"
- "ସଂଯୋଗ କରନ୍ତୁ"
- "ସେଟ ଅପ କରନ୍ତୁ"
- "ସେଟିଂସ"
-
diff --git a/nearby/halfsheet/res/values-pa/strings.xml b/nearby/halfsheet/res/values-pa/strings.xml
deleted file mode 100644
index f0523a3a3962ba3df958bec64dd742283be7cafa..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/values-pa/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
- "ਸੈੱਟਅੱਪ ਸ਼ੁਰੂ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ…"
- "ਡੀਵਾਈਸ ਸੈੱਟਅੱਪ ਕਰੋ"
- "ਡੀਵਾਈਸ ਕਨੈਕਟ ਕੀਤਾ ਗਿਆ"
- "ਕਨੈਕਟ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਿਆ"
- "ਹੋ ਗਿਆ"
- "ਰੱਖਿਅਤ ਕਰੋ"
- "ਕਨੈਕਟ ਕਰੋ"
- "ਸੈੱਟਅੱਪ ਕਰੋ"
- "ਸੈਟਿੰਗਾਂ"
-
diff --git a/nearby/halfsheet/res/values-pl/strings.xml b/nearby/halfsheet/res/values-pl/strings.xml
deleted file mode 100644
index 5abf5fd34b4bc75fa32bca3e17498ede0615ae1f..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/values-pl/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
- "Rozpoczynam konfigurowanie…"
- "Skonfiguruj urządzenie"
- "Urządzenie połączone"
- "Nie udało się połączyć"
- "Gotowe"
- "Zapisz"
- "Połącz"
- "Skonfiguruj"
- "Ustawienia"
-
diff --git a/nearby/halfsheet/res/values-pt-rBR/strings.xml b/nearby/halfsheet/res/values-pt-rBR/strings.xml
deleted file mode 100644
index b021b3924fbfe90e01f31ad18bbc6bf9de0fe795..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/values-pt-rBR/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
- "Iniciando a configuração…"
- "Configurar dispositivo"
- "Dispositivo conectado"
- "Erro ao conectar"
- "Concluído"
- "Salvar"
- "Conectar"
- "Configurar"
- "Configurações"
-
diff --git a/nearby/halfsheet/res/values-pt-rPT/strings.xml b/nearby/halfsheet/res/values-pt-rPT/strings.xml
deleted file mode 100644
index 3285c73e9c8349f15929ea6a698622e40799573a..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/values-pt-rPT/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
- "A iniciar a configuração…"
- "Configure o dispositivo"
- "Dispositivo ligado"
- "Não foi possível ligar"
- "Concluir"
- "Guardar"
- "Ligar"
- "Configurar"
- "Definições"
-
diff --git a/nearby/halfsheet/res/values-pt/strings.xml b/nearby/halfsheet/res/values-pt/strings.xml
deleted file mode 100644
index b021b3924fbfe90e01f31ad18bbc6bf9de0fe795..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/values-pt/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
- "Iniciando a configuração…"
- "Configurar dispositivo"
- "Dispositivo conectado"
- "Erro ao conectar"
- "Concluído"
- "Salvar"
- "Conectar"
- "Configurar"
- "Configurações"
-
diff --git a/nearby/halfsheet/res/values-ro/strings.xml b/nearby/halfsheet/res/values-ro/strings.xml
deleted file mode 100644
index 189f698dd9c7d8a2c799ece78948d939a740758e..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/values-ro/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
- "Începe configurarea…"
- "Configurează dispozitivul"
- "Dispozitivul s-a conectat"
- "Nu s-a putut conecta"
- "Gata"
- "Salvează"
- "Conectează"
- "Configurează"
- "Setări"
-
diff --git a/nearby/halfsheet/res/values-ru/strings.xml b/nearby/halfsheet/res/values-ru/strings.xml
deleted file mode 100644
index ee869dff91df38caf4df10d6b422282e444efc48..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/values-ru/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
- "Начинаем настройку…"
- "Настройка устройства"
- "Устройство подключено"
- "Ошибка подключения"
- "Готово"
- "Сохранить"
- "Подключить"
- "Настроить"
- "Открыть настройки"
-
diff --git a/nearby/halfsheet/res/values-si/strings.xml b/nearby/halfsheet/res/values-si/strings.xml
deleted file mode 100644
index f4274c27aa5cd35d187004f379d951360a6bfbee..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/values-si/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
- "පිහිටුවීම ආරම්භ කරමින්…"
- "උපාංගය පිහිටුවන්න"
- "උපාංගය සම්බන්ධිතයි"
- "සම්බන්ධ කළ නොහැකි විය"
- "නිමයි"
- "සුරකින්න"
- "සම්බන්ධ කරන්න"
- "පිහිටුවන්න"
- "සැකසීම්"
-
diff --git a/nearby/halfsheet/res/values-sk/strings.xml b/nearby/halfsheet/res/values-sk/strings.xml
deleted file mode 100644
index 46c45af3e24db892705846ac2ddedb95edb13a30..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/values-sk/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
- "Spúšťa sa nastavenie…"
- "Nastavte zariadenie"
- "Zariadenie bolo pripojené"
- "Nepodarilo sa pripojiť"
- "Hotovo"
- "Uložiť"
- "Pripojiť"
- "Nastaviť"
- "Nastavenia"
-
diff --git a/nearby/halfsheet/res/values-sl/strings.xml b/nearby/halfsheet/res/values-sl/strings.xml
deleted file mode 100644
index e4f3c91a3a1c95da2c2f22a28da806573b09ad01..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/values-sl/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
- "Začetek nastavitve …"
- "Nastavitev naprave"
- "Naprava je povezana"
- "Povezava ni mogoča"
- "Končano"
- "Shrani"
- "Poveži"
- "Nastavi"
- "Nastavitve"
-
diff --git a/nearby/halfsheet/res/values-sq/strings.xml b/nearby/halfsheet/res/values-sq/strings.xml
deleted file mode 100644
index 9265d1f63d6c011ed59698b101ad1473a66603f9..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/values-sq/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
- "Po nis konfigurimin…"
- "Konfiguro pajisjen"
- "Pajisja u lidh"
- "Nuk mund të lidhej"
- "U krye"
- "Ruaj"
- "Lidh"
- "Konfiguro"
- "Cilësimet"
-
diff --git a/nearby/halfsheet/res/values-sr/strings.xml b/nearby/halfsheet/res/values-sr/strings.xml
deleted file mode 100644
index 094be03a6fb5a2171fab2e70b6a3367dad2e3e85..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/values-sr/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
- "Подешавање се покреће…"
- "Подесите уређај"
- "Уређај је повезан"
- "Повезивање није успело"
- "Готово"
- "Сачувај"
- "Повежи"
- "Подеси"
- "Подешавања"
-
diff --git a/nearby/halfsheet/res/values-sv/strings.xml b/nearby/halfsheet/res/values-sv/strings.xml
deleted file mode 100644
index 297b7bc5622466d62751655a844d2041e3f06d39..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/values-sv/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
- "Konfigureringen startas …"
- "Konfigurera enheten"
- "Enheten är ansluten"
- "Det gick inte att ansluta"
- "Klar"
- "Spara"
- "Anslut"
- "Konfigurera"
- "Inställningar"
-
diff --git a/nearby/halfsheet/res/values-sw/strings.xml b/nearby/halfsheet/res/values-sw/strings.xml
deleted file mode 100644
index bf0bfebc877cb933c951e68940fc1064ef9a3162..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/values-sw/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
- "Inaanza Kuweka Mipangilio…"
- "Weka mipangilio ya kifaa"
- "Kifaa kimeunganishwa"
- "Imeshindwa kuunganisha"
- "Imemaliza"
- "Hifadhi"
- "Unganisha"
- "Weka mipangilio"
- "Mipangilio"
-
diff --git a/nearby/halfsheet/res/values-ta/strings.xml b/nearby/halfsheet/res/values-ta/strings.xml
deleted file mode 100644
index dfd67a6fb21148d10ef219c47110537414a8b0c2..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/values-ta/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
- "அமைவைத் தொடங்குகிறது…"
- "சாதனத்தை அமையுங்கள்"
- "சாதனம் இணைக்கப்பட்டது"
- "இணைக்க முடியவில்லை"
- "முடிந்தது"
- "சேமி"
- "இணை"
- "அமை"
- "அமைப்புகள்"
-
diff --git a/nearby/halfsheet/res/values-te/strings.xml b/nearby/halfsheet/res/values-te/strings.xml
deleted file mode 100644
index 87be14563ffcf8b35a267dca002e81b7a1db65f4..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/values-te/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
- "సెటప్ ప్రారంభమవుతోంది…"
- "పరికరాన్ని సెటప్ చేయండి"
- "పరికరం కనెక్ట్ చేయబడింది"
- "కనెక్ట్ చేయడం సాధ్యపడలేదు"
- "పూర్తయింది"
- "సేవ్ చేయండి"
- "కనెక్ట్ చేయండి"
- "సెటప్ చేయండి"
- "సెట్టింగ్లు"
-
diff --git a/nearby/halfsheet/res/values-th/strings.xml b/nearby/halfsheet/res/values-th/strings.xml
deleted file mode 100644
index bc4296bd2250851aed4ff2a66e7bfa501e26fc22..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/values-th/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
- "กำลังเริ่มการตั้งค่า…"
- "ตั้งค่าอุปกรณ์"
- "เชื่อมต่ออุปกรณ์แล้ว"
- "เชื่อมต่อไม่ได้"
- "เสร็จสิ้น"
- "บันทึก"
- "เชื่อมต่อ"
- "ตั้งค่า"
- "การตั้งค่า"
-
diff --git a/nearby/halfsheet/res/values-tl/strings.xml b/nearby/halfsheet/res/values-tl/strings.xml
deleted file mode 100644
index a6de0e8f9a564dcf7acbc93dc8ce65f5593c43a8..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/values-tl/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
- "Sinisimulan ang Pag-set Up…"
- "I-set up ang device"
- "Naikonekta na ang device"
- "Hindi makakonekta"
- "Tapos na"
- "I-save"
- "Kumonekta"
- "I-set up"
- "Mga Setting"
-
diff --git a/nearby/halfsheet/res/values-tr/strings.xml b/nearby/halfsheet/res/values-tr/strings.xml
deleted file mode 100644
index cd5a6ea9b0ca4178203241ca20ea557189819085..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/values-tr/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
- "Kurulum Başlatılıyor…"
- "Cihazı kur"
- "Cihaz bağlandı"
- "Bağlanamadı"
- "Bitti"
- "Kaydet"
- "Bağlan"
- "Kur"
- "Ayarlar"
-
diff --git a/nearby/halfsheet/res/values-uk/strings.xml b/nearby/halfsheet/res/values-uk/strings.xml
deleted file mode 100644
index 242ca07a06b521772481fed318067752ed67f4a8..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/values-uk/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
- "Запуск налаштування…"
- "Налаштуйте пристрій"
- "Пристрій підключено"
- "Не вдалося підключити"
- "Готово"
- "Зберегти"
- "Підключити"
- "Налаштувати"
- "Налаштування"
-
diff --git a/nearby/halfsheet/res/values-ur/strings.xml b/nearby/halfsheet/res/values-ur/strings.xml
deleted file mode 100644
index 4a4a59caa688ad8ac4ae68e795a2b218a3a77367..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/values-ur/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
- "سیٹ اپ شروع ہو رہا ہے…"
- "آلہ سیٹ اپ کریں"
- "آلہ منسلک ہے"
- "منسلک نہیں ہو سکا"
- "ہو گیا"
- "محفوظ کریں"
- "منسلک کریں"
- "سیٹ اپ کریں"
- "ترتیبات"
-
diff --git a/nearby/halfsheet/res/values-uz/strings.xml b/nearby/halfsheet/res/values-uz/strings.xml
deleted file mode 100644
index 420512daa0d5aca37342a5b0722d7b3bc7e1141c..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/values-uz/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
- "Sozlash boshlandi…"
- "Qurilmani sozlash"
- "Qurilma ulandi"
- "Ulanmadi"
- "Tayyor"
- "Saqlash"
- "Ulanish"
- "Sozlash"
- "Sozlamalar"
-
diff --git a/nearby/halfsheet/res/values-vi/strings.xml b/nearby/halfsheet/res/values-vi/strings.xml
deleted file mode 100644
index 9c1e052981c544b472ab624738adf84115e2f4e4..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/values-vi/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
- "Đang bắt đầu thiết lập…"
- "Thiết lập thiết bị"
- "Đã kết nối thiết bị"
- "Không kết nối được"
- "Xong"
- "Lưu"
- "Kết nối"
- "Thiết lập"
- "Cài đặt"
-
diff --git a/nearby/halfsheet/res/values-zh-rCN/strings.xml b/nearby/halfsheet/res/values-zh-rCN/strings.xml
deleted file mode 100644
index 482b5c4f92ed88be0af63f55e6f82c9e15a49a99..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/values-zh-rCN/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
- "正在启动设置…"
- "设置设备"
- "设备已连接"
- "无法连接"
- "完成"
- "保存"
- "连接"
- "设置"
- "设置"
-
diff --git a/nearby/halfsheet/res/values-zh-rHK/strings.xml b/nearby/halfsheet/res/values-zh-rHK/strings.xml
deleted file mode 100644
index 3ca73e6aa89eda92bccee95bb0298b9112328c23..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/values-zh-rHK/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
- "開始設定…"
- "設定裝置"
- "已連接裝置"
- "無法連接"
- "完成"
- "儲存"
- "連接"
- "設定"
- "設定"
-
diff --git a/nearby/halfsheet/res/values-zh-rTW/strings.xml b/nearby/halfsheet/res/values-zh-rTW/strings.xml
deleted file mode 100644
index b4e680d866210e7a25f5699b8772d283ee66502b..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/values-zh-rTW/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
- "正在啟動設定程序…"
- "設定裝置"
- "裝置已連線"
- "無法連線"
- "完成"
- "儲存"
- "連線"
- "設定"
- "設定"
-
diff --git a/nearby/halfsheet/res/values-zu/strings.xml b/nearby/halfsheet/res/values-zu/strings.xml
deleted file mode 100644
index 33fb405837921960e1b272f92d6953d2f343c66e..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/values-zu/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
- "Iqalisa Ukusetha…"
- "Setha idivayisi"
- "Idivayisi ixhunyiwe"
- "Ayikwazanga ukuxhuma"
- "Kwenziwe"
- "Londoloza"
- "Xhuma"
- "Setha"
- "Amasethingi"
-
diff --git a/nearby/halfsheet/res/values/colors.xml b/nearby/halfsheet/res/values/colors.xml
deleted file mode 100644
index b0666655040d72f1f514de6934c80e2eef7ae1cf..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/values/colors.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-
-
-
- #00000000
-
- @android:color/system_accent1_100
- @android:color/system_neutral1_900
- @android:color/system_neutral1_900
- @android:color/system_accent1_600
- @android:color/system_neutral2_700
- @android:color/system_neutral1_900
-
-
- #4285F4
-
-
- #DE000000
- #24000000
- #D93025
- #80868B
- #FFFFFF
- #1A73E8
- #F44336
- #24000000
-
diff --git a/nearby/halfsheet/res/values/dimens.xml b/nearby/halfsheet/res/values/dimens.xml
deleted file mode 100644
index f843042adb64848b0e6355b48272ddc8665fb35f..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/values/dimens.xml
+++ /dev/null
@@ -1,42 +0,0 @@
-
-
-
- 160dp
- 14sp
- 11sp
- 4dp
- 8dp
- 8dp
- 40dp
- 64dp
- 32dp
- 3dp
- 350dp
- 215dp
- 136dp
- 36dp
- 48dp
- 152dp
- 100dp
- 156
- 182
-
-
- 360dp
-
- 16dp
- 70dp
- 4dp
-
- 4dp
- 32dp
- 32dp
-
- 0dp
- 0dp
- 0dp
- 0dp
- 0dp
-
- 48dp
-
diff --git a/nearby/halfsheet/res/values/ints.xml b/nearby/halfsheet/res/values/ints.xml
deleted file mode 100644
index 07bf9d2347c1b8c16653be075c51d2df3094a951..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/values/ints.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
- 250
- 250
-
diff --git a/nearby/halfsheet/res/values/overlayable.xml b/nearby/halfsheet/res/values/overlayable.xml
deleted file mode 100644
index fffa2e357e4cbc101b0b11f1e122ef5a6b52296a..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/values/overlayable.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/nearby/halfsheet/res/values/strings.xml b/nearby/halfsheet/res/values/strings.xml
deleted file mode 100644
index 01a82e4c352374789b4063b14c6e37aeac3bf68e..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/values/strings.xml
+++ /dev/null
@@ -1,72 +0,0 @@
-
-
-
-
-
-
-
- Starting Setup…
-
- Set up device
-
- Device connected
-
- Couldn\'t connect
-
-
-
-
- Done
-
- Save
-
- Connect
-
- Set up
-
- Settings
-
\ No newline at end of file
diff --git a/nearby/halfsheet/res/values/styles.xml b/nearby/halfsheet/res/values/styles.xml
deleted file mode 100644
index 917bb63cfd6fa508c9370c3854d5ea87858b0244..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/res/values/styles.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-
-
-
-
-
-
-
-
-
diff --git a/nearby/halfsheet/src/com/android/nearby/halfsheet/FastPairUiServiceClient.java b/nearby/halfsheet/src/com/android/nearby/halfsheet/FastPairUiServiceClient.java
deleted file mode 100644
index bec0c0aff783743af9a8c9a8ca66032c26a65394..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/src/com/android/nearby/halfsheet/FastPairUiServiceClient.java
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.nearby.halfsheet;
-
-import android.content.Context;
-import android.nearby.FastPairDevice;
-import android.nearby.FastPairStatusCallback;
-import android.nearby.PairStatusMetadata;
-import android.nearby.aidl.IFastPairStatusCallback;
-import android.nearby.aidl.IFastPairUiService;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.util.Log;
-
-import androidx.annotation.BinderThread;
-import androidx.annotation.UiThread;
-
-import java.lang.ref.WeakReference;
-
-/**
- * A utility class for connecting to the {@link IFastPairUiService} and receive callbacks.
- *
- * @hide
- */
-@UiThread
-public class FastPairUiServiceClient {
-
- private static final String TAG = "FastPairHalfSheet";
-
- private final IBinder mBinder;
- private final WeakReference mWeakContext;
- IFastPairUiService mFastPairUiService;
- PairStatusCallbackIBinder mPairStatusCallbackIBinder;
-
- /**
- * The Ibinder instance should be from
- * {@link com.android.server.nearby.fastpair.halfsheet.FastPairUiServiceImpl} so that the client can
- * talk with the service.
- */
- public FastPairUiServiceClient(Context context, IBinder binder) {
- mBinder = binder;
- mFastPairUiService = IFastPairUiService.Stub.asInterface(mBinder);
- mWeakContext = new WeakReference<>(context);
- }
-
- /**
- * Registers a callback at service to get UI updates.
- */
- public void registerHalfSheetStateCallBack(FastPairStatusCallback fastPairStatusCallback) {
- if (mPairStatusCallbackIBinder != null) {
- return;
- }
- mPairStatusCallbackIBinder = new PairStatusCallbackIBinder(fastPairStatusCallback);
- try {
- mFastPairUiService.registerCallback(mPairStatusCallbackIBinder);
- } catch (RemoteException e) {
- Log.w(TAG, "Failed to register fastPairStatusCallback", e);
- }
- }
-
- /**
- * Pairs the device at service.
- */
- public void connect(FastPairDevice fastPairDevice) {
- try {
- mFastPairUiService.connect(fastPairDevice);
- } catch (RemoteException e) {
- Log.w(TAG, "Failed to connect Fast Pair device" + fastPairDevice, e);
- }
- }
-
- /**
- * Cancels Fast Pair connection and dismisses half sheet.
- */
- public void cancel(FastPairDevice fastPairDevice) {
- try {
- mFastPairUiService.cancel(fastPairDevice);
- } catch (RemoteException e) {
- Log.w(TAG, "Failed to connect Fast Pair device" + fastPairDevice, e);
- }
- }
-
- private class PairStatusCallbackIBinder extends IFastPairStatusCallback.Stub {
- private final FastPairStatusCallback mStatusCallback;
-
- private PairStatusCallbackIBinder(FastPairStatusCallback fastPairStatusCallback) {
- mStatusCallback = fastPairStatusCallback;
- }
-
- @BinderThread
- @Override
- public synchronized void onPairUpdate(FastPairDevice fastPairDevice,
- PairStatusMetadata pairStatusMetadata) {
- Context context = mWeakContext.get();
- if (context != null) {
- Handler handler = new Handler(context.getMainLooper());
- handler.post(() ->
- mStatusCallback.onPairUpdate(fastPairDevice, pairStatusMetadata));
- }
- }
- }
-}
diff --git a/nearby/halfsheet/src/com/android/nearby/halfsheet/HalfSheetActivity.java b/nearby/halfsheet/src/com/android/nearby/halfsheet/HalfSheetActivity.java
deleted file mode 100644
index 07e57763760ab1d3dac01d3a91c3fbb6ebc5ada6..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/src/com/android/nearby/halfsheet/HalfSheetActivity.java
+++ /dev/null
@@ -1,242 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.nearby.halfsheet;
-
-import static android.Manifest.permission.ACCESS_FINE_LOCATION;
-
-import static com.android.nearby.halfsheet.fragment.DevicePairingFragment.APP_LAUNCH_FRAGMENT_TYPE;
-import static com.android.server.nearby.common.bluetooth.fastpair.FastPairConstants.EXTRA_MODEL_ID;
-import static com.android.server.nearby.common.fastpair.service.UserActionHandlerBase.EXTRA_MAC_ADDRESS;
-import static com.android.server.nearby.fastpair.Constant.ACTION_FAST_PAIR_HALF_SHEET_CANCEL;
-import static com.android.server.nearby.fastpair.Constant.DEVICE_PAIRING_FRAGMENT_TYPE;
-import static com.android.server.nearby.fastpair.Constant.EXTRA_HALF_SHEET_INFO;
-import static com.android.server.nearby.fastpair.Constant.EXTRA_HALF_SHEET_TYPE;
-
-import android.content.Intent;
-import android.os.Bundle;
-import android.util.Log;
-import android.widget.TextView;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.fragment.app.FragmentActivity;
-
-import com.android.nearby.halfsheet.fragment.DevicePairingFragment;
-import com.android.nearby.halfsheet.fragment.HalfSheetModuleFragment;
-import com.android.nearby.halfsheet.utils.BroadcastUtils;
-
-import com.google.protobuf.InvalidProtocolBufferException;
-
-import java.util.Locale;
-
-import service.proto.Cache;
-
-/**
- * A class show Fast Pair related information in Half sheet format.
- */
-public class HalfSheetActivity extends FragmentActivity {
-
- public static final String TAG = "FastPairHalfSheet";
-
- public static final String EXTRA_HALF_SHEET_CONTENT =
- "com.android.nearby.halfsheet.HALF_SHEET_CONTENT";
- public static final String EXTRA_TITLE =
- "com.android.nearby.halfsheet.HALF_SHEET_TITLE";
- public static final String EXTRA_DESCRIPTION =
- "com.android.nearby.halfsheet.HALF_SHEET_DESCRIPTION";
- public static final String EXTRA_HALF_SHEET_ID =
- "com.android.nearby.halfsheet.HALF_SHEET_ID";
- public static final String EXTRA_HALF_SHEET_IS_RETROACTIVE =
- "com.android.nearby.halfsheet.HALF_SHEET_IS_RETROACTIVE";
- public static final String EXTRA_HALF_SHEET_IS_SUBSEQUENT_PAIR =
- "com.android.nearby.halfsheet.HALF_SHEET_IS_SUBSEQUENT_PAIR";
- public static final String EXTRA_HALF_SHEET_PAIRING_RESURFACE =
- "com.android.nearby.halfsheet.EXTRA_HALF_SHEET_PAIRING_RESURFACE";
- public static final String ACTION_HALF_SHEET_FOREGROUND_STATE =
- "com.android.nearby.halfsheet.ACTION_HALF_SHEET_FOREGROUND_STATE";
- // Intent extra contains the user gmail name eg. testaccount@gmail.com.
- public static final String EXTRA_HALF_SHEET_ACCOUNT_NAME =
- "com.android.nearby.halfsheet.HALF_SHEET_ACCOUNT_NAME";
- public static final String EXTRA_HALF_SHEET_FOREGROUND =
- "com.android.nearby.halfsheet.EXTRA_HALF_SHEET_FOREGROUND";
- public static final String ARG_FRAGMENT_STATE = "ARG_FRAGMENT_STATE";
- @Nullable
- private HalfSheetModuleFragment mHalfSheetModuleFragment;
- @Nullable
- private Cache.ScanFastPairStoreItem mScanFastPairStoreItem;
-
- @Override
- protected void onCreate(@Nullable Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- byte[] infoArray = getIntent().getByteArrayExtra(EXTRA_HALF_SHEET_INFO);
- String fragmentType = getIntent().getStringExtra(EXTRA_HALF_SHEET_TYPE);
- if (infoArray == null || fragmentType == null) {
- Log.d(
- "HalfSheetActivity",
- "exit flag off or do not have enough half sheet information.");
- finish();
- return;
- }
-
- switch (fragmentType) {
- case DEVICE_PAIRING_FRAGMENT_TYPE:
- mHalfSheetModuleFragment = DevicePairingFragment.newInstance(getIntent(),
- savedInstanceState);
- if (mHalfSheetModuleFragment == null) {
- Log.d(TAG, "device pairing fragment has error.");
- finish();
- return;
- }
- break;
- case APP_LAUNCH_FRAGMENT_TYPE:
- // currentFragment = AppLaunchFragment.newInstance(getIntent());
- if (mHalfSheetModuleFragment == null) {
- Log.v(TAG, "app launch fragment has error.");
- finish();
- return;
- }
- break;
- default:
- Log.w(TAG, "there is no valid type for half sheet");
- finish();
- return;
- }
- if (mHalfSheetModuleFragment != null) {
- getSupportFragmentManager()
- .beginTransaction()
- .replace(R.id.fragment_container, mHalfSheetModuleFragment)
- .commit();
- }
- setContentView(R.layout.fast_pair_half_sheet);
-
- // If the user taps on the background, then close the activity.
- // Unless they tap on the card itself, then ignore the tap.
- findViewById(R.id.background).setOnClickListener(v -> onCancelClicked());
- findViewById(R.id.card)
- .setOnClickListener(
- v -> Log.v(TAG, "card view is clicked noop"));
- try {
- mScanFastPairStoreItem =
- Cache.ScanFastPairStoreItem.parseFrom(infoArray);
- } catch (InvalidProtocolBufferException e) {
- Log.w(
- TAG, "error happens when pass info to half sheet");
- }
- }
-
- @Override
- protected void onStart() {
- super.onStart();
- }
-
- @Override
- protected void onSaveInstanceState(@NonNull Bundle savedInstanceState) {
- super.onSaveInstanceState(savedInstanceState);
- if (mHalfSheetModuleFragment != null) {
- mHalfSheetModuleFragment.onSaveInstanceState(savedInstanceState);
- }
- }
-
- @Override
- public void onBackPressed() {
- super.onBackPressed();
- sendHalfSheetCancelBroadcast();
- }
-
- @Override
- protected void onUserLeaveHint() {
- super.onUserLeaveHint();
- sendHalfSheetCancelBroadcast();
- }
-
- @Override
- protected void onNewIntent(Intent intent) {
- super.onNewIntent(intent);
- String fragmentType = getIntent().getStringExtra(EXTRA_HALF_SHEET_TYPE);
- if (fragmentType == null) {
- return;
- }
- if (fragmentType.equals(DEVICE_PAIRING_FRAGMENT_TYPE)
- && intent.getExtras() != null
- && intent.getByteArrayExtra(EXTRA_HALF_SHEET_INFO) != null) {
- try {
- Cache.ScanFastPairStoreItem testScanFastPairStoreItem =
- Cache.ScanFastPairStoreItem.parseFrom(
- intent.getByteArrayExtra(EXTRA_HALF_SHEET_INFO));
- if (mScanFastPairStoreItem != null
- && !testScanFastPairStoreItem.getAddress().equals(
- mScanFastPairStoreItem.getAddress())
- && testScanFastPairStoreItem.getModelId().equals(
- mScanFastPairStoreItem.getModelId())) {
- Log.d(TAG, "possible factory reset happens");
- halfSheetStateChange();
- }
- } catch (InvalidProtocolBufferException | NullPointerException e) {
- Log.w(TAG, "error happens when pass info to half sheet");
- }
- }
- }
-
- /** This function should be called when user click empty area and cancel button. */
- public void onCancelClicked() {
- Log.d(TAG, "Cancels the half sheet and paring.");
- sendHalfSheetCancelBroadcast();
- finish();
- }
-
- /** Changes the half sheet foreground state to false. */
- public void halfSheetStateChange() {
- BroadcastUtils.sendBroadcast(
- this,
- new Intent(ACTION_HALF_SHEET_FOREGROUND_STATE)
- .putExtra(EXTRA_HALF_SHEET_FOREGROUND, false));
- finish();
- }
-
- private void sendHalfSheetCancelBroadcast() {
- BroadcastUtils.sendBroadcast(
- this,
- new Intent(ACTION_HALF_SHEET_FOREGROUND_STATE)
- .putExtra(EXTRA_HALF_SHEET_FOREGROUND, false));
- if (mScanFastPairStoreItem != null) {
- BroadcastUtils.sendBroadcast(
- this,
- new Intent(ACTION_FAST_PAIR_HALF_SHEET_CANCEL)
- .putExtra(EXTRA_MODEL_ID,
- mScanFastPairStoreItem.getModelId().toLowerCase(Locale.ROOT))
- .putExtra(EXTRA_HALF_SHEET_TYPE,
- getIntent().getStringExtra(EXTRA_HALF_SHEET_TYPE))
- .putExtra(
- EXTRA_HALF_SHEET_IS_SUBSEQUENT_PAIR,
- getIntent().getBooleanExtra(EXTRA_HALF_SHEET_IS_SUBSEQUENT_PAIR,
- false))
- .putExtra(
- EXTRA_HALF_SHEET_IS_RETROACTIVE,
- getIntent().getBooleanExtra(EXTRA_HALF_SHEET_IS_RETROACTIVE,
- false))
- .putExtra(EXTRA_MAC_ADDRESS, mScanFastPairStoreItem.getAddress()),
- ACCESS_FINE_LOCATION);
- }
- }
-
- @Override
- public void setTitle(CharSequence title) {
- super.setTitle(title);
- TextView toolbarTitle = findViewById(R.id.toolbar_title);
- toolbarTitle.setText(title);
- }
-}
diff --git a/nearby/halfsheet/src/com/android/nearby/halfsheet/fragment/DevicePairingFragment.java b/nearby/halfsheet/src/com/android/nearby/halfsheet/fragment/DevicePairingFragment.java
deleted file mode 100644
index 320965b424f6b585f06e456a65db3c362ac4d297..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/src/com/android/nearby/halfsheet/fragment/DevicePairingFragment.java
+++ /dev/null
@@ -1,487 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.nearby.halfsheet.fragment;
-
-import static android.text.TextUtils.isEmpty;
-
-import static com.android.nearby.halfsheet.HalfSheetActivity.ARG_FRAGMENT_STATE;
-import static com.android.nearby.halfsheet.HalfSheetActivity.EXTRA_DESCRIPTION;
-import static com.android.nearby.halfsheet.HalfSheetActivity.EXTRA_HALF_SHEET_ACCOUNT_NAME;
-import static com.android.nearby.halfsheet.HalfSheetActivity.EXTRA_HALF_SHEET_CONTENT;
-import static com.android.nearby.halfsheet.HalfSheetActivity.EXTRA_HALF_SHEET_ID;
-import static com.android.nearby.halfsheet.HalfSheetActivity.EXTRA_TITLE;
-import static com.android.nearby.halfsheet.HalfSheetActivity.TAG;
-import static com.android.nearby.halfsheet.fragment.HalfSheetModuleFragment.HalfSheetFragmentState.FAILED;
-import static com.android.nearby.halfsheet.fragment.HalfSheetModuleFragment.HalfSheetFragmentState.FOUND_DEVICE;
-import static com.android.nearby.halfsheet.fragment.HalfSheetModuleFragment.HalfSheetFragmentState.NOT_STARTED;
-import static com.android.nearby.halfsheet.fragment.HalfSheetModuleFragment.HalfSheetFragmentState.PAIRED_LAUNCHABLE;
-import static com.android.nearby.halfsheet.fragment.HalfSheetModuleFragment.HalfSheetFragmentState.PAIRED_UNLAUNCHABLE;
-import static com.android.nearby.halfsheet.fragment.HalfSheetModuleFragment.HalfSheetFragmentState.PAIRING;
-import static com.android.server.nearby.fastpair.Constant.EXTRA_BINDER;
-import static com.android.server.nearby.fastpair.Constant.EXTRA_BUNDLE;
-import static com.android.server.nearby.fastpair.Constant.EXTRA_HALF_SHEET_INFO;
-
-import android.bluetooth.BluetoothDevice;
-import android.content.Intent;
-import android.content.res.Configuration;
-import android.graphics.Bitmap;
-import android.nearby.FastPairDevice;
-import android.nearby.FastPairStatusCallback;
-import android.nearby.NearbyDevice;
-import android.nearby.PairStatusMetadata;
-import android.os.Bundle;
-import android.provider.Settings;
-import android.text.TextUtils;
-import android.util.DisplayMetrics;
-import android.util.Log;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.Button;
-import android.widget.ImageView;
-import android.widget.ProgressBar;
-import android.widget.TextView;
-
-import androidx.annotation.Nullable;
-
-import com.android.nearby.halfsheet.FastPairUiServiceClient;
-import com.android.nearby.halfsheet.HalfSheetActivity;
-import com.android.nearby.halfsheet.R;
-import com.android.nearby.halfsheet.utils.FastPairUtils;
-import com.android.nearby.halfsheet.utils.IconUtils;
-
-import com.google.protobuf.InvalidProtocolBufferException;
-
-import java.util.Objects;
-
-import service.proto.Cache.ScanFastPairStoreItem;
-
-/**
- * Modularize half sheet for fast pair this fragment will show when half sheet does device pairing.
- *
- *
This fragment will handle initial pairing subsequent pairing and retroactive pairing.
- */
-@SuppressWarnings("nullness")
-public class DevicePairingFragment extends HalfSheetModuleFragment implements
- FastPairStatusCallback {
- private TextView mTitleView;
- private TextView mSubTitleView;
- private ImageView mImage;
-
- private Button mConnectButton;
- private Button mSetupButton;
- private Button mCancelButton;
- // Opens Bluetooth Settings.
- private Button mSettingsButton;
- private ImageView mInfoIconButton;
- private ProgressBar mConnectProgressBar;
-
- private Bundle mBundle;
-
- private ScanFastPairStoreItem mScanFastPairStoreItem;
- private FastPairUiServiceClient mFastPairUiServiceClient;
-
- private @PairStatusMetadata.Status int mPairStatus = PairStatusMetadata.Status.UNKNOWN;
- // True when there is a companion app to open.
- private boolean mIsLaunchable;
- private boolean mIsConnecting;
- // Indicates that the setup button is clicked before.
- private boolean mSetupButtonClicked = false;
-
- // Holds the new text while we transition between the two.
- private static final int TAG_PENDING_TEXT = R.id.toolbar_title;
- public static final String APP_LAUNCH_FRAGMENT_TYPE = "APP_LAUNCH";
-
- private static final String ARG_SETUP_BUTTON_CLICKED = "SETUP_BUTTON_CLICKED";
- private static final String ARG_PAIRING_RESULT = "PAIRING_RESULT";
-
- /**
- * Create certain fragment according to the intent.
- */
- @Nullable
- public static HalfSheetModuleFragment newInstance(
- Intent intent, @Nullable Bundle saveInstanceStates) {
- Bundle args = new Bundle();
- byte[] infoArray = intent.getByteArrayExtra(EXTRA_HALF_SHEET_INFO);
-
- Bundle bundle = intent.getBundleExtra(EXTRA_BUNDLE);
- String title = intent.getStringExtra(EXTRA_TITLE);
- String description = intent.getStringExtra(EXTRA_DESCRIPTION);
- String accountName = intent.getStringExtra(EXTRA_HALF_SHEET_ACCOUNT_NAME);
- String result = intent.getStringExtra(EXTRA_HALF_SHEET_CONTENT);
- int halfSheetId = intent.getIntExtra(EXTRA_HALF_SHEET_ID, 0);
-
- args.putByteArray(EXTRA_HALF_SHEET_INFO, infoArray);
- args.putString(EXTRA_HALF_SHEET_ACCOUNT_NAME, accountName);
- args.putString(EXTRA_TITLE, title);
- args.putString(EXTRA_DESCRIPTION, description);
- args.putInt(EXTRA_HALF_SHEET_ID, halfSheetId);
- args.putString(EXTRA_HALF_SHEET_CONTENT, result == null ? "" : result);
- args.putBundle(EXTRA_BUNDLE, bundle);
- if (saveInstanceStates != null) {
- if (saveInstanceStates.containsKey(ARG_FRAGMENT_STATE)) {
- args.putSerializable(
- ARG_FRAGMENT_STATE, saveInstanceStates.getSerializable(ARG_FRAGMENT_STATE));
- }
- if (saveInstanceStates.containsKey(BluetoothDevice.EXTRA_DEVICE)) {
- args.putParcelable(
- BluetoothDevice.EXTRA_DEVICE,
- saveInstanceStates.getParcelable(BluetoothDevice.EXTRA_DEVICE));
- }
- if (saveInstanceStates.containsKey(BluetoothDevice.EXTRA_PAIRING_KEY)) {
- args.putInt(
- BluetoothDevice.EXTRA_PAIRING_KEY,
- saveInstanceStates.getInt(BluetoothDevice.EXTRA_PAIRING_KEY));
- }
- if (saveInstanceStates.containsKey(ARG_SETUP_BUTTON_CLICKED)) {
- args.putBoolean(
- ARG_SETUP_BUTTON_CLICKED,
- saveInstanceStates.getBoolean(ARG_SETUP_BUTTON_CLICKED));
- }
- if (saveInstanceStates.containsKey(ARG_PAIRING_RESULT)) {
- args.putBoolean(ARG_PAIRING_RESULT,
- saveInstanceStates.getBoolean(ARG_PAIRING_RESULT));
- }
- }
- DevicePairingFragment fragment = new DevicePairingFragment();
- fragment.setArguments(args);
- return fragment;
- }
-
- @Nullable
- @Override
- public View onCreateView(
- LayoutInflater inflater, @Nullable ViewGroup container,
- @Nullable Bundle savedInstanceState) {
- /* attachToRoot= */
- View rootView = inflater.inflate(
- R.layout.fast_pair_device_pairing_fragment, container, /* attachToRoot= */
- false);
- if (getContext() == null) {
- Log.d(TAG, "can't find the attached activity");
- return rootView;
- }
-
- Bundle args = getArguments();
- byte[] storeFastPairItemBytesArray = args.getByteArray(EXTRA_HALF_SHEET_INFO);
- mBundle = args.getBundle(EXTRA_BUNDLE);
- if (mBundle != null) {
- mFastPairUiServiceClient =
- new FastPairUiServiceClient(getContext(), mBundle.getBinder(EXTRA_BINDER));
- mFastPairUiServiceClient.registerHalfSheetStateCallBack(this);
- }
- if (args.containsKey(ARG_FRAGMENT_STATE)) {
- mFragmentState = (HalfSheetFragmentState) args.getSerializable(ARG_FRAGMENT_STATE);
- }
- if (args.containsKey(ARG_SETUP_BUTTON_CLICKED)) {
- mSetupButtonClicked = args.getBoolean(ARG_SETUP_BUTTON_CLICKED);
- }
- if (args.containsKey(ARG_PAIRING_RESULT)) {
- mPairStatus = args.getInt(ARG_PAIRING_RESULT);
- }
-
- // Initiate views.
- mTitleView = Objects.requireNonNull(getActivity()).findViewById(R.id.toolbar_title);
- mSubTitleView = rootView.findViewById(R.id.header_subtitle);
- mImage = rootView.findViewById(R.id.pairing_pic);
- mConnectProgressBar = rootView.findViewById(R.id.connect_progressbar);
- mConnectButton = rootView.findViewById(R.id.connect_btn);
- mCancelButton = rootView.findViewById(R.id.cancel_btn);
- mSettingsButton = rootView.findViewById(R.id.settings_btn);
- mSetupButton = rootView.findViewById(R.id.setup_btn);
- mInfoIconButton = rootView.findViewById(R.id.info_icon);
- mInfoIconButton.setImageResource(R.drawable.fast_pair_ic_info);
-
- try {
- setScanFastPairStoreItem(ScanFastPairStoreItem.parseFrom(storeFastPairItemBytesArray));
- } catch (InvalidProtocolBufferException e) {
- Log.w(TAG,
- "DevicePairingFragment: error happens when pass info to half sheet");
- return rootView;
- }
-
- // Config for landscape mode
- DisplayMetrics displayMetrics = getContext().getResources().getDisplayMetrics();
- if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
- rootView.getLayoutParams().height = displayMetrics.heightPixels * 4 / 5;
- rootView.getLayoutParams().width = displayMetrics.heightPixels * 4 / 5;
- mImage.getLayoutParams().height = displayMetrics.heightPixels / 2;
- mImage.getLayoutParams().width = displayMetrics.heightPixels / 2;
- mConnectProgressBar.getLayoutParams().width = displayMetrics.heightPixels / 2;
- mConnectButton.getLayoutParams().width = displayMetrics.heightPixels / 2;
- //TODO(b/213373051): Add cancel button
- }
-
- Bitmap icon = IconUtils.getIcon(mScanFastPairStoreItem.getIconPng().toByteArray(),
- mScanFastPairStoreItem.getIconPng().size());
- if (icon != null) {
- mImage.setImageBitmap(icon);
- }
- mConnectButton.setOnClickListener(v -> onConnectClick());
- mCancelButton.setOnClickListener(v ->
- ((HalfSheetActivity) getActivity()).onCancelClicked());
- mSettingsButton.setOnClickListener(v -> onSettingsClicked());
- mSetupButton.setOnClickListener(v -> onSetupClick());
-
- return rootView;
- }
-
- @Override
- public void onCreate(@Nullable Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- // Get access to the activity's menu
- setHasOptionsMenu(true);
- }
-
- @Override
- public void onStart() {
- super.onStart();
- Log.v(TAG, "onStart: invalidate states");
- invalidateState();
- }
-
- @Override
- public void onSaveInstanceState(Bundle savedInstanceState) {
- super.onSaveInstanceState(savedInstanceState);
-
- savedInstanceState.putSerializable(ARG_FRAGMENT_STATE, mFragmentState);
- savedInstanceState.putBoolean(ARG_SETUP_BUTTON_CLICKED, mSetupButtonClicked);
- savedInstanceState.putInt(ARG_PAIRING_RESULT, mPairStatus);
- }
-
- private void onSettingsClicked() {
- startActivity(new Intent(Settings.ACTION_BLUETOOTH_SETTINGS));
- }
-
- private void onSetupClick() {
- String companionApp =
- FastPairUtils.getCompanionAppFromActionUrl(mScanFastPairStoreItem.getActionUrl());
- Intent intent =
- FastPairUtils.createCompanionAppIntent(
- Objects.requireNonNull(getContext()),
- companionApp,
- mScanFastPairStoreItem.getAddress());
- mSetupButtonClicked = true;
- if (mFragmentState == PAIRED_LAUNCHABLE) {
- if (intent != null) {
- startActivity(intent);
- }
- } else {
- Log.d(TAG, "onSetupClick: State is " + mFragmentState);
- }
- }
-
- private void onConnectClick() {
- if (mScanFastPairStoreItem == null) {
- Log.w(TAG, "No pairing related information in half sheet");
- return;
- }
- if (getFragmentState() == PAIRING) {
- return;
- }
- mIsConnecting = true;
- invalidateState();
- mFastPairUiServiceClient.connect(
- new FastPairDevice.Builder()
- .addMedium(NearbyDevice.Medium.BLE)
- .setBluetoothAddress(mScanFastPairStoreItem.getAddress())
- .setData(FastPairUtils.convertFrom(mScanFastPairStoreItem)
- .toByteArray())
- .build());
- }
-
- // Receives callback from service.
- @Override
- public void onPairUpdate(FastPairDevice fastPairDevice, PairStatusMetadata pairStatusMetadata) {
- @PairStatusMetadata.Status int status = pairStatusMetadata.getStatus();
- if (status == PairStatusMetadata.Status.DISMISS && getActivity() != null) {
- getActivity().finish();
- }
- mIsConnecting = false;
- mPairStatus = status;
- invalidateState();
- }
-
- @Override
- public void invalidateState() {
- HalfSheetFragmentState newState = NOT_STARTED;
- if (mIsConnecting) {
- newState = PAIRING;
- } else {
- switch (mPairStatus) {
- case PairStatusMetadata.Status.SUCCESS:
- newState = mIsLaunchable ? PAIRED_LAUNCHABLE : PAIRED_UNLAUNCHABLE;
- break;
- case PairStatusMetadata.Status.FAIL:
- newState = FAILED;
- break;
- default:
- if (mScanFastPairStoreItem != null) {
- newState = FOUND_DEVICE;
- }
- }
- }
- if (newState == mFragmentState) {
- return;
- }
- setState(newState);
- }
-
- @Override
- public void setState(HalfSheetFragmentState state) {
- super.setState(state);
- invalidateTitles();
- invalidateButtons();
- }
-
- private void setScanFastPairStoreItem(ScanFastPairStoreItem item) {
- mScanFastPairStoreItem = item;
- invalidateLaunchable();
- }
-
- private void invalidateLaunchable() {
- String companionApp =
- FastPairUtils.getCompanionAppFromActionUrl(mScanFastPairStoreItem.getActionUrl());
- if (isEmpty(companionApp)) {
- mIsLaunchable = false;
- return;
- }
- mIsLaunchable =
- FastPairUtils.isLaunchable(Objects.requireNonNull(getContext()), companionApp);
- }
-
- private void invalidateButtons() {
- mConnectProgressBar.setVisibility(View.INVISIBLE);
- mConnectButton.setVisibility(View.INVISIBLE);
- mCancelButton.setVisibility(View.INVISIBLE);
- mSetupButton.setVisibility(View.INVISIBLE);
- mSettingsButton.setVisibility(View.INVISIBLE);
- mInfoIconButton.setVisibility(View.INVISIBLE);
-
- switch (mFragmentState) {
- case FOUND_DEVICE:
- mInfoIconButton.setVisibility(View.VISIBLE);
- mConnectButton.setVisibility(View.VISIBLE);
- break;
- case PAIRING:
- mConnectProgressBar.setVisibility(View.VISIBLE);
- mCancelButton.setVisibility(View.VISIBLE);
- setBackgroundClickable(false);
- break;
- case PAIRED_LAUNCHABLE:
- mCancelButton.setVisibility(View.VISIBLE);
- mSetupButton.setVisibility(View.VISIBLE);
- setBackgroundClickable(true);
- break;
- case FAILED:
- mSettingsButton.setVisibility(View.VISIBLE);
- setBackgroundClickable(true);
- break;
- case NOT_STARTED:
- case PAIRED_UNLAUNCHABLE:
- default:
- mCancelButton.setVisibility(View.VISIBLE);
- setBackgroundClickable(true);
- }
- }
-
- private void setBackgroundClickable(boolean isClickable) {
- HalfSheetActivity activity = (HalfSheetActivity) getActivity();
- if (activity == null) {
- Log.w(TAG, "setBackgroundClickable: failed to set clickable to " + isClickable
- + " because cannot get HalfSheetActivity.");
- return;
- }
- View background = activity.findViewById(R.id.background);
- if (background == null) {
- Log.w(TAG, "setBackgroundClickable: failed to set clickable to " + isClickable
- + " cannot find background at HalfSheetActivity.");
- return;
- }
- Log.d(TAG, "setBackgroundClickable to " + isClickable);
- background.setClickable(isClickable);
- }
-
- private void invalidateTitles() {
- String newTitle = getTitle();
- invalidateTextView(mTitleView, newTitle);
- String newSubTitle = getSubTitle();
- invalidateTextView(mSubTitleView, newSubTitle);
- }
-
- private void invalidateTextView(TextView textView, String newText) {
- CharSequence oldText =
- textView.getTag(TAG_PENDING_TEXT) != null
- ? (CharSequence) textView.getTag(TAG_PENDING_TEXT)
- : textView.getText();
- if (TextUtils.equals(oldText, newText)) {
- return;
- }
- if (TextUtils.isEmpty(oldText)) {
- // First time run. Don't animate since there's nothing to animate from.
- textView.setText(newText);
- } else {
- textView.setTag(TAG_PENDING_TEXT, newText);
- textView
- .animate()
- .alpha(0f)
- .setDuration(TEXT_ANIMATION_DURATION_MILLISECONDS)
- .withEndAction(
- () -> {
- textView.setText(newText);
- textView
- .animate()
- .alpha(1f)
- .setDuration(TEXT_ANIMATION_DURATION_MILLISECONDS);
- });
- }
- }
-
- private String getTitle() {
- switch (mFragmentState) {
- case PAIRED_LAUNCHABLE:
- return getString(R.string.fast_pair_title_setup);
- case FAILED:
- return getString(R.string.fast_pair_title_fail);
- case FOUND_DEVICE:
- case NOT_STARTED:
- case PAIRED_UNLAUNCHABLE:
- default:
- return mScanFastPairStoreItem.getDeviceName();
- }
- }
-
- private String getSubTitle() {
- switch (mFragmentState) {
- case PAIRED_LAUNCHABLE:
- return String.format(
- mScanFastPairStoreItem
- .getFastPairStrings()
- .getPairingFinishedCompanionAppInstalled(),
- mScanFastPairStoreItem.getDeviceName());
- case FAILED:
- return mScanFastPairStoreItem.getFastPairStrings().getPairingFailDescription();
- case PAIRED_UNLAUNCHABLE:
- getString(R.string.fast_pair_device_ready);
- // fall through
- case FOUND_DEVICE:
- case NOT_STARTED:
- return mScanFastPairStoreItem.getFastPairStrings().getInitialPairingDescription();
- default:
- return "";
- }
- }
-}
diff --git a/nearby/halfsheet/src/com/android/nearby/halfsheet/fragment/HalfSheetModuleFragment.java b/nearby/halfsheet/src/com/android/nearby/halfsheet/fragment/HalfSheetModuleFragment.java
deleted file mode 100644
index f1db4d0f5ee6a36b4bbcdd20d3376d75a6058cb3..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/src/com/android/nearby/halfsheet/fragment/HalfSheetModuleFragment.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.nearby.halfsheet.fragment;
-
-import static com.android.nearby.halfsheet.HalfSheetActivity.TAG;
-import static com.android.nearby.halfsheet.fragment.HalfSheetModuleFragment.HalfSheetFragmentState.NOT_STARTED;
-
-import android.os.Bundle;
-import android.util.Log;
-
-import androidx.annotation.Nullable;
-import androidx.fragment.app.Fragment;
-
-
-/** Base class for all of the half sheet fragment. */
-public abstract class HalfSheetModuleFragment extends Fragment {
-
- static final int TEXT_ANIMATION_DURATION_MILLISECONDS = 200;
-
- HalfSheetFragmentState mFragmentState = NOT_STARTED;
-
- @Override
- public void onCreate(@Nullable Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- }
-
- @Override
- public void onDestroy() {
- super.onDestroy();
- }
-
- /** UI states of the half-sheet fragment. */
- public enum HalfSheetFragmentState {
- NOT_STARTED, // Initial status
- FOUND_DEVICE, // When a device is found found from Nearby scan service
- PAIRING, // When user taps 'Connect' and Fast Pair stars pairing process
- PAIRED_LAUNCHABLE, // When pair successfully
- // and we found a launchable companion app installed
- PAIRED_UNLAUNCHABLE, // When pair successfully
- // but we cannot find a companion app to launch it
- FAILED, // When paring was failed
- FINISHED // When the activity is about to end finished.
- }
-
- /**
- * Returns the {@link HalfSheetFragmentState} to the parent activity.
- *
- *
Overrides this method if the fragment's state needs to be preserved in the parent
- * activity.
- */
- public HalfSheetFragmentState getFragmentState() {
- return mFragmentState;
- }
-
- void setState(HalfSheetFragmentState state) {
- Log.v(TAG, "Settings state from " + mFragmentState + " to " + state);
- mFragmentState = state;
- }
-
- /**
- * Populate data to UI widgets according to the latest {@link HalfSheetFragmentState}.
- */
- abstract void invalidateState();
-}
diff --git a/nearby/halfsheet/src/com/android/nearby/halfsheet/utils/BroadcastUtils.java b/nearby/halfsheet/src/com/android/nearby/halfsheet/utils/BroadcastUtils.java
deleted file mode 100644
index 2f1e90ae6930fd4865b876e2ff935d03562cc11b..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/src/com/android/nearby/halfsheet/utils/BroadcastUtils.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.nearby.halfsheet.utils;
-
-import android.content.Context;
-import android.content.Intent;
-
-/**
- * Broadcast util class
- */
-public class BroadcastUtils {
-
- /**
- * Helps send broadcast.
- */
- public static void sendBroadcast(Context context, Intent intent) {
- context.sendBroadcast(intent);
- }
-
- /**
- * Helps send a broadcast with specified receiver permission.
- */
- public static void sendBroadcast(Context context, Intent intent, String receiverPermission) {
- context.sendBroadcast(intent, receiverPermission);
- }
-
- private BroadcastUtils() {
- }
-}
diff --git a/nearby/halfsheet/src/com/android/nearby/halfsheet/utils/FastPairUtils.java b/nearby/halfsheet/src/com/android/nearby/halfsheet/utils/FastPairUtils.java
deleted file mode 100644
index 00a365c259ee8ad61371b8be93fc42ae86902609..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/src/com/android/nearby/halfsheet/utils/FastPairUtils.java
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.nearby.halfsheet.utils;
-
-import static com.android.server.nearby.common.fastpair.service.UserActionHandlerBase.EXTRA_COMPANION_APP;
-import static com.android.server.nearby.fastpair.UserActionHandler.ACTION_FAST_PAIR;
-
-import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.BluetoothDevice;
-import android.bluetooth.BluetoothManager;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.util.Log;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import java.net.URISyntaxException;
-
-import service.proto.Cache;
-
-/**
- * Util class in half sheet apk
- */
-public class FastPairUtils {
-
- /** FastPair util method check certain app is install on the device or not. */
- public static boolean isAppInstalled(Context context, String packageName) {
- try {
- context.getPackageManager().getPackageInfo(packageName, 0);
- return true;
- } catch (PackageManager.NameNotFoundException e) {
- return false;
- }
- }
-
- /** FastPair util method to properly format the action url extra. */
- @Nullable
- public static String getCompanionAppFromActionUrl(String actionUrl) {
- try {
- Intent intent = Intent.parseUri(actionUrl, Intent.URI_INTENT_SCHEME);
- if (!intent.getAction().equals(ACTION_FAST_PAIR)) {
- Log.e("FastPairUtils", "Companion app launch attempted from malformed action url");
- return null;
- }
- return intent.getStringExtra(EXTRA_COMPANION_APP);
- } catch (URISyntaxException e) {
- Log.e("FastPairUtils", "FastPair: fail to get companion app info from discovery item");
- return null;
- }
- }
-
- /**
- * Converts {@link service.proto.Cache.StoredDiscoveryItem} from
- * {@link service.proto.Cache.ScanFastPairStoreItem}
- */
- public static Cache.StoredDiscoveryItem convertFrom(Cache.ScanFastPairStoreItem item) {
- return convertFrom(item, /* isSubsequentPair= */ false);
- }
-
- /**
- * Converts a {@link service.proto.Cache.ScanFastPairStoreItem}
- * to a {@link service.proto.Cache.StoredDiscoveryItem}.
- *
- *
This is needed to make the new Fast Pair scanning stack compatible with the rest of the
- * legacy Fast Pair code.
- */
- public static Cache.StoredDiscoveryItem convertFrom(
- Cache.ScanFastPairStoreItem item, boolean isSubsequentPair) {
- return Cache.StoredDiscoveryItem.newBuilder()
- .setId(item.getModelId())
- .setFirstObservationTimestampMillis(item.getFirstObservationTimestampMillis())
- .setLastObservationTimestampMillis(item.getLastObservationTimestampMillis())
- .setActionUrl(item.getActionUrl())
- .setActionUrlType(Cache.ResolvedUrlType.APP)
- .setTitle(
- isSubsequentPair
- ? item.getFastPairStrings().getTapToPairWithoutAccount()
- : item.getDeviceName())
- .setMacAddress(item.getAddress())
- .setState(Cache.StoredDiscoveryItem.State.STATE_ENABLED)
- .setTriggerId(item.getModelId())
- .setIconPng(item.getIconPng())
- .setIconFifeUrl(item.getIconFifeUrl())
- .setDescription(
- isSubsequentPair
- ? item.getDeviceName()
- : item.getFastPairStrings().getTapToPairWithoutAccount())
- .setAuthenticationPublicKeySecp256R1(item.getAntiSpoofingPublicKey())
- .setCompanionDetail(item.getCompanionDetail())
- .setFastPairStrings(item.getFastPairStrings())
- .setFastPairInformation(
- Cache.FastPairInformation.newBuilder()
- .setDataOnlyConnection(item.getDataOnlyConnection())
- .setTrueWirelessImages(item.getTrueWirelessImages())
- .setAssistantSupported(item.getAssistantSupported())
- .setCompanyName(item.getCompanyName()))
- .build();
- }
-
- /**
- * Returns true the application is installed and can be opened on device.
- */
- public static boolean isLaunchable(@NonNull Context context, String companionApp) {
- return isAppInstalled(context, companionApp)
- && createCompanionAppIntent(context, companionApp, null) != null;
- }
-
- /**
- * Returns an intent to launch given the package name and bluetooth address (if provided).
- * Returns null if no such an intent can be found.
- */
- @Nullable
- public static Intent createCompanionAppIntent(@NonNull Context context, String packageName,
- @Nullable String address) {
- Intent intent = context.getPackageManager().getLaunchIntentForPackage(packageName);
- if (intent == null) {
- return null;
- }
- if (address != null) {
- BluetoothAdapter adapter = getBluetoothAdapter(context);
- if (adapter != null) {
- intent.putExtra(BluetoothDevice.EXTRA_DEVICE, adapter.getRemoteDevice(address));
- }
- }
- return intent;
- }
-
- @Nullable
- private static BluetoothAdapter getBluetoothAdapter(@NonNull Context context) {
- BluetoothManager bluetoothManager = context.getSystemService(BluetoothManager.class);
- return bluetoothManager == null ? null : bluetoothManager.getAdapter();
- }
-
- private FastPairUtils() {}
-}
diff --git a/nearby/halfsheet/src/com/android/nearby/halfsheet/utils/IconUtils.java b/nearby/halfsheet/src/com/android/nearby/halfsheet/utils/IconUtils.java
deleted file mode 100644
index 218c756070120372bf78b9ec6a4149b68d7b9308..0000000000000000000000000000000000000000
--- a/nearby/halfsheet/src/com/android/nearby/halfsheet/utils/IconUtils.java
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.nearby.halfsheet.utils;
-
-import static com.android.nearby.halfsheet.HalfSheetActivity.TAG;
-
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Paint;
-import android.util.Log;
-
-import androidx.annotation.Nullable;
-import androidx.core.graphics.ColorUtils;
-
-/**
- * Utility class for icon size verification.
- */
-public class IconUtils {
-
- private static final float NOTIFICATION_BACKGROUND_PADDING_PERCENT = 0.125f;
- private static final float NOTIFICATION_BACKGROUND_ALPHA = 0.7f;
- private static final int MIN_ICON_SIZE = 16;
- private static final int DESIRED_ICON_SIZE = 32;
-
- /**
- * Verify that the icon is non null and falls in the small bucket. Just because an icon isn't
- * small doesn't guarantee it is large or exists.
- */
- public static boolean isIconSizedSmall(@Nullable Bitmap bitmap) {
- if (bitmap == null) {
- return false;
- }
- return bitmap.getWidth() >= MIN_ICON_SIZE
- && bitmap.getWidth() < DESIRED_ICON_SIZE
- && bitmap.getHeight() >= MIN_ICON_SIZE
- && bitmap.getHeight() < DESIRED_ICON_SIZE;
- }
-
- /**
- * Verify that the icon is non null and falls in the regular / default size bucket. Doesn't
- * guarantee if not regular then it is small.
- */
- static boolean isIconSizedRegular(@Nullable Bitmap bitmap) {
- if (bitmap == null) {
- return false;
- }
- return bitmap.getWidth() >= DESIRED_ICON_SIZE && bitmap.getHeight() >= DESIRED_ICON_SIZE;
- }
-
- /**
- * All icons that are sized correctly (larger than the MIN_ICON_SIZE icon size)
- * are resize on the server to the DESIRED_ICON_SIZE icon size so that
- * they appear correct.
- */
- public static boolean isIconSizeCorrect(@Nullable Bitmap bitmap) {
- if (bitmap == null) {
- return false;
- }
- return isIconSizedSmall(bitmap) || isIconSizedRegular(bitmap);
- }
-
- /**
- * Returns the bitmap from the byte array. Returns null if cannot decode or not in correct size.
- */
- @Nullable
- public static Bitmap getIcon(byte[] imageData, int size) {
- try {
- Bitmap icon =
- BitmapFactory.decodeByteArray(imageData, /* offset= */ 0, size);
- if (IconUtils.isIconSizeCorrect(icon)) {
- // Do not add background for Half Sheet.
- return IconUtils.addWhiteCircleBackground(icon);
- }
- } catch (OutOfMemoryError e) {
- Log.w(TAG, "getIcon: Failed to decode icon, returning null.", e);
- }
- return null;
- }
-
- /** Adds a circular, white background to the bitmap. */
- @Nullable
- public static Bitmap addWhiteCircleBackground(Bitmap bitmap) {
- if (bitmap == null) {
- Log.w(TAG, "addWhiteCircleBackground: Bitmap is null, not adding background.");
- return null;
- }
-
- if (bitmap.getWidth() != bitmap.getHeight()) {
- Log.w(TAG, "addWhiteCircleBackground: Bitmap dimensions not square. Skipping"
- + "adding background.");
- return bitmap;
- }
-
- int padding = (int) (bitmap.getWidth() * NOTIFICATION_BACKGROUND_PADDING_PERCENT);
- Bitmap bitmapWithBackground =
- Bitmap.createBitmap(
- bitmap.getWidth() + (2 * padding),
- bitmap.getHeight() + (2 * padding),
- bitmap.getConfig());
- Canvas canvas = new Canvas(bitmapWithBackground);
- Paint paint = new Paint();
- paint.setColor(
- ColorUtils.setAlphaComponent(
- Color.WHITE, (int) (255 * NOTIFICATION_BACKGROUND_ALPHA)));
- paint.setStyle(Paint.Style.FILL);
- paint.setAntiAlias(true);
- canvas.drawCircle(
- bitmapWithBackground.getWidth() / 2,
- bitmapWithBackground.getHeight() / 2,
- bitmapWithBackground.getWidth() / 2,
- paint);
- canvas.drawBitmap(bitmap, padding, padding, null);
-
- return bitmapWithBackground;
- }
-}
-
diff --git a/nearby/service/Android.bp b/nearby/service/Android.bp
index 684b1331888aa6063efb69724a5e3ba5013ec77c..46309026b6de1c2dc07242a420cca53f614bffcd 100644
--- a/nearby/service/Android.bp
+++ b/nearby/service/Android.bp
@@ -24,57 +24,6 @@ filegroup {
],
}
-filegroup {
- name: "nearby-service-string-res",
- srcs: [
- "java/**/Constant.java",
- "java/**/UserActionHandlerBase.java",
- "java/**/UserActionHandler.java",
- "java/**/FastPairConstants.java",
- ],
-}
-
-java_library {
- name: "nearby-service-string",
- srcs: [":nearby-service-string-res"],
- libs: ["framework-bluetooth"],
- sdk_version: "module_current",
-}
-
-// Common lib for nearby end-to-end testing.
-java_library {
- name: "nearby-common-lib",
- srcs: [
- "java/com/android/server/nearby/common/bloomfilter/*.java",
- "java/com/android/server/nearby/common/bluetooth/*.java",
- "java/com/android/server/nearby/common/bluetooth/fastpair/AesCtrMultipleBlockEncryption.java",
- "java/com/android/server/nearby/common/bluetooth/fastpair/AesEcbSingleBlockEncryption.java",
- "java/com/android/server/nearby/common/bluetooth/fastpair/BluetoothAddress.java",
- "java/com/android/server/nearby/common/bluetooth/fastpair/BluetoothUuids.java",
- "java/com/android/server/nearby/common/bluetooth/fastpair/Bytes.java",
- "java/com/android/server/nearby/common/bluetooth/fastpair/Constants.java",
- "java/com/android/server/nearby/common/bluetooth/fastpair/EllipticCurveDiffieHellmanExchange.java",
- "java/com/android/server/nearby/common/bluetooth/fastpair/HmacSha256.java",
- "java/com/android/server/nearby/common/bluetooth/fastpair/Ltv.java",
- "java/com/android/server/nearby/common/bluetooth/fastpair/MessageStreamHmacEncoder.java",
- "java/com/android/server/nearby/common/bluetooth/fastpair/NamingEncoder.java",
- "java/com/android/server/nearby/common/bluetooth/testability/**/*.java",
- "java/com/android/server/nearby/common/bluetooth/gatt/*.java",
- "java/com/android/server/nearby/common/bluetooth/util/*.java",
- ],
- libs: [
- "androidx.annotation_annotation",
- "androidx.core_core",
- "error_prone_annotations",
- "framework-bluetooth",
- "guava",
- ],
- sdk_version: "module_current",
- visibility: [
- "//packages/modules/Connectivity/nearby/tests/multidevices/clients/test_support/fastpair_provider",
- ],
-}
-
// Main lib for nearby services.
java_library {
name: "service-nearby-pre-jarjar",
@@ -95,7 +44,6 @@ java_library {
"androidx.core_core",
"guava",
"libprotobuf-java-lite",
- "fast-pair-lite-protos",
"modules-utils-build",
"modules-utils-handlerexecutor",
"modules-utils-preconditions",
diff --git a/nearby/service/java/com/android/server/nearby/NearbyService.java b/nearby/service/java/com/android/server/nearby/NearbyService.java
index 5ebf1e5edd4411ed90a4fd1c5d5c4da05cd2e288..12201048b927feb0bf481ff639a0099c2af206c2 100644
--- a/nearby/service/java/com/android/server/nearby/NearbyService.java
+++ b/nearby/service/java/com/android/server/nearby/NearbyService.java
@@ -18,7 +18,6 @@ package com.android.server.nearby;
import static com.android.server.SystemService.PHASE_BOOT_COMPLETED;
import static com.android.server.SystemService.PHASE_SYSTEM_SERVICES_READY;
-import static com.android.server.SystemService.PHASE_THIRD_PARTY_APPS_CAN_START;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
@@ -39,13 +38,10 @@ import android.nearby.ScanRequest;
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.server.nearby.common.locator.LocatorContextWrapper;
-import com.android.server.nearby.fastpair.FastPairManager;
import com.android.server.nearby.injector.ContextHubManagerAdapter;
import com.android.server.nearby.injector.Injector;
import com.android.server.nearby.provider.BroadcastProviderManager;
import com.android.server.nearby.provider.DiscoveryProviderManager;
-import com.android.server.nearby.provider.FastPairDataProvider;
import com.android.server.nearby.util.identity.CallerIdentity;
import com.android.server.nearby.util.permissions.BroadcastPermissions;
import com.android.server.nearby.util.permissions.DiscoveryPermissions;
@@ -56,7 +52,6 @@ public class NearbyService extends INearbyManager.Stub {
private final Context mContext;
private Injector mInjector;
- private final FastPairManager mFastPairManager;
private final BroadcastReceiver mBluetoothReceiver =
new BroadcastReceiver() {
@Override
@@ -82,8 +77,6 @@ public class NearbyService extends INearbyManager.Stub {
mInjector = new SystemInjector(context);
mProviderManager = new DiscoveryProviderManager(context, mInjector);
mBroadcastProviderManager = new BroadcastProviderManager(context, mInjector);
- final LocatorContextWrapper lcw = new LocatorContextWrapper(context, null);
- mFastPairManager = new FastPairManager(lcw);
}
@VisibleForTesting
@@ -152,10 +145,6 @@ public class NearbyService extends INearbyManager.Stub {
((SystemInjector) mInjector).initializeAppOpsManager();
}
break;
- case PHASE_THIRD_PARTY_APPS_CAN_START:
- // Ensures that a fast pair data provider exists which will work in direct boot.
- FastPairDataProvider.init(mContext);
- break;
case PHASE_BOOT_COMPLETED:
if (mInjector instanceof SystemInjector) {
// The nearby service must be functioning after this boot phase.
@@ -166,7 +155,6 @@ public class NearbyService extends INearbyManager.Stub {
mContext.registerReceiver(
mBluetoothReceiver,
new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED));
- mFastPairManager.initiate();
break;
}
}
diff --git a/nearby/service/java/com/android/server/nearby/common/ble/BleFilter.java b/nearby/service/java/com/android/server/nearby/common/ble/BleFilter.java
deleted file mode 100644
index 23d5170947b454c62c6dcd0c12b007d020dc81b4..0000000000000000000000000000000000000000
--- a/nearby/service/java/com/android/server/nearby/common/ble/BleFilter.java
+++ /dev/null
@@ -1,746 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.nearby.common.ble;
-
-import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.BluetoothDevice;
-import android.bluetooth.le.ScanFilter;
-import android.os.Parcel;
-import android.os.ParcelUuid;
-import android.os.Parcelable;
-import android.text.TextUtils;
-
-import androidx.annotation.Nullable;
-
-import java.util.Arrays;
-import java.util.List;
-import java.util.Objects;
-import java.util.UUID;
-
-/**
- * Criteria for filtering BLE devices. A {@link BleFilter} allows clients to restrict BLE devices to
- * only those that are of interest to them.
- *
- *
- *
Current filtering on the following fields are supported:
- *
Service UUIDs which identify the bluetooth gatt services running on the device.
- *
Name of remote Bluetooth LE device.
- *
Mac address of the remote device.
- *
Service data which is the data associated with a service.
- *
Manufacturer specific data which is the data associated with a particular manufacturer.
- *
- * @see BleSighting
- */
-public final class BleFilter implements Parcelable {
-
- @Nullable
- private String mDeviceName;
-
- @Nullable
- private String mDeviceAddress;
-
- @Nullable
- private ParcelUuid mServiceUuid;
-
- @Nullable
- private ParcelUuid mServiceUuidMask;
-
- @Nullable
- private ParcelUuid mServiceDataUuid;
-
- @Nullable
- private byte[] mServiceData;
-
- @Nullable
- private byte[] mServiceDataMask;
-
- private int mManufacturerId;
-
- @Nullable
- private byte[] mManufacturerData;
-
- @Nullable
- private byte[] mManufacturerDataMask;
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- BleFilter() {
- }
-
- BleFilter(
- @Nullable String deviceName,
- @Nullable String deviceAddress,
- @Nullable ParcelUuid serviceUuid,
- @Nullable ParcelUuid serviceUuidMask,
- @Nullable ParcelUuid serviceDataUuid,
- @Nullable byte[] serviceData,
- @Nullable byte[] serviceDataMask,
- int manufacturerId,
- @Nullable byte[] manufacturerData,
- @Nullable byte[] manufacturerDataMask) {
- this.mDeviceName = deviceName;
- this.mDeviceAddress = deviceAddress;
- this.mServiceUuid = serviceUuid;
- this.mServiceUuidMask = serviceUuidMask;
- this.mServiceDataUuid = serviceDataUuid;
- this.mServiceData = serviceData;
- this.mServiceDataMask = serviceDataMask;
- this.mManufacturerId = manufacturerId;
- this.mManufacturerData = manufacturerData;
- this.mManufacturerDataMask = manufacturerDataMask;
- }
-
- public static final Parcelable.Creator CREATOR = new Creator() {
- @Override
- public BleFilter createFromParcel(Parcel source) {
- BleFilter nBleFilter = new BleFilter();
- nBleFilter.mDeviceName = source.readString();
- nBleFilter.mDeviceAddress = source.readString();
- nBleFilter.mManufacturerId = source.readInt();
- nBleFilter.mManufacturerData = source.marshall();
- nBleFilter.mManufacturerDataMask = source.marshall();
- nBleFilter.mServiceDataUuid = source.readParcelable(null);
- nBleFilter.mServiceData = source.marshall();
- nBleFilter.mServiceDataMask = source.marshall();
- nBleFilter.mServiceUuid = source.readParcelable(null);
- nBleFilter.mServiceUuidMask = source.readParcelable(null);
- return nBleFilter;
- }
-
- @Override
- public BleFilter[] newArray(int size) {
- return new BleFilter[size];
- }
- };
-
-
- /** Returns the filter set on the device name field of Bluetooth advertisement data. */
- @Nullable
- public String getDeviceName() {
- return mDeviceName;
- }
-
- /** Returns the filter set on the service uuid. */
- @Nullable
- public ParcelUuid getServiceUuid() {
- return mServiceUuid;
- }
-
- /** Returns the mask for the service uuid. */
- @Nullable
- public ParcelUuid getServiceUuidMask() {
- return mServiceUuidMask;
- }
-
- /** Returns the filter set on the device address. */
- @Nullable
- public String getDeviceAddress() {
- return mDeviceAddress;
- }
-
- /** Returns the filter set on the service data. */
- @Nullable
- public byte[] getServiceData() {
- return mServiceData;
- }
-
- /** Returns the mask for the service data. */
- @Nullable
- public byte[] getServiceDataMask() {
- return mServiceDataMask;
- }
-
- /** Returns the filter set on the service data uuid. */
- @Nullable
- public ParcelUuid getServiceDataUuid() {
- return mServiceDataUuid;
- }
-
- /** Returns the manufacturer id. -1 if the manufacturer filter is not set. */
- public int getManufacturerId() {
- return mManufacturerId;
- }
-
- /** Returns the filter set on the manufacturer data. */
- @Nullable
- public byte[] getManufacturerData() {
- return mManufacturerData;
- }
-
- /** Returns the mask for the manufacturer data. */
- @Nullable
- public byte[] getManufacturerDataMask() {
- return mManufacturerDataMask;
- }
-
- /**
- * Check if the filter matches a {@code BleSighting}. A BLE sighting is considered as a match if
- * it matches all the field filters.
- */
- public boolean matches(@Nullable BleSighting bleSighting) {
- if (bleSighting == null) {
- return false;
- }
- BluetoothDevice device = bleSighting.getDevice();
- // Device match.
- if (mDeviceAddress != null && (device == null || !mDeviceAddress.equals(
- device.getAddress()))) {
- return false;
- }
-
- BleRecord bleRecord = bleSighting.getBleRecord();
-
- // Scan record is null but there exist filters on it.
- if (bleRecord == null
- && (mDeviceName != null
- || mServiceUuid != null
- || mManufacturerData != null
- || mServiceData != null)) {
- return false;
- }
-
- // Local name match.
- if (mDeviceName != null && !mDeviceName.equals(bleRecord.getDeviceName())) {
- return false;
- }
-
- // UUID match.
- if (mServiceUuid != null
- && !matchesServiceUuids(mServiceUuid, mServiceUuidMask,
- bleRecord.getServiceUuids())) {
- return false;
- }
-
- // Service data match
- if (mServiceDataUuid != null
- && !matchesPartialData(
- mServiceData, mServiceDataMask, bleRecord.getServiceData(mServiceDataUuid))) {
- return false;
- }
-
- // Manufacturer data match.
- if (mManufacturerId >= 0
- && !matchesPartialData(
- mManufacturerData,
- mManufacturerDataMask,
- bleRecord.getManufacturerSpecificData(mManufacturerId))) {
- return false;
- }
-
- // All filters match.
- return true;
- }
-
- /**
- * Determines if the characteristics of this filter are a superset of the characteristics of the
- * given filter.
- */
- public boolean isSuperset(@Nullable BleFilter bleFilter) {
- if (bleFilter == null) {
- return false;
- }
-
- if (equals(bleFilter)) {
- return true;
- }
-
- // Verify device address matches.
- if (mDeviceAddress != null && !mDeviceAddress.equals(bleFilter.getDeviceAddress())) {
- return false;
- }
-
- // Verify device name matches.
- if (mDeviceName != null && !mDeviceName.equals(bleFilter.getDeviceName())) {
- return false;
- }
-
- // Verify UUID is a superset.
- if (mServiceUuid != null
- && !serviceUuidIsSuperset(
- mServiceUuid,
- mServiceUuidMask,
- bleFilter.getServiceUuid(),
- bleFilter.getServiceUuidMask())) {
- return false;
- }
-
- // Verify service data is a superset.
- if (mServiceDataUuid != null
- && (!mServiceDataUuid.equals(bleFilter.getServiceDataUuid())
- || !partialDataIsSuperset(
- mServiceData,
- mServiceDataMask,
- bleFilter.getServiceData(),
- bleFilter.getServiceDataMask()))) {
- return false;
- }
-
- // Verify manufacturer data is a superset.
- if (mManufacturerId >= 0
- && (mManufacturerId != bleFilter.getManufacturerId()
- || !partialDataIsSuperset(
- mManufacturerData,
- mManufacturerDataMask,
- bleFilter.getManufacturerData(),
- bleFilter.getManufacturerDataMask()))) {
- return false;
- }
-
- return true;
- }
-
- /** Determines if the first uuid and mask are a superset of the second uuid and mask. */
- private static boolean serviceUuidIsSuperset(
- @Nullable ParcelUuid uuid1,
- @Nullable ParcelUuid uuidMask1,
- @Nullable ParcelUuid uuid2,
- @Nullable ParcelUuid uuidMask2) {
- // First uuid1 is null so it can match any service UUID.
- if (uuid1 == null) {
- return true;
- }
-
- // uuid2 is a superset of uuid1, but not the other way around.
- if (uuid2 == null) {
- return false;
- }
-
- // Without a mask, the uuids must match.
- if (uuidMask1 == null) {
- return uuid1.equals(uuid2);
- }
-
- // Mask2 should be at least as specific as mask1.
- if (uuidMask2 != null) {
- long uuid1MostSig = uuidMask1.getUuid().getMostSignificantBits();
- long uuid1LeastSig = uuidMask1.getUuid().getLeastSignificantBits();
- long uuid2MostSig = uuidMask2.getUuid().getMostSignificantBits();
- long uuid2LeastSig = uuidMask2.getUuid().getLeastSignificantBits();
- if (((uuid1MostSig & uuid2MostSig) != uuid1MostSig)
- || ((uuid1LeastSig & uuid2LeastSig) != uuid1LeastSig)) {
- return false;
- }
- }
-
- if (!matchesServiceUuids(uuid1, uuidMask1, Arrays.asList(uuid2))) {
- return false;
- }
-
- return true;
- }
-
- /** Determines if the first data and mask are the superset of the second data and mask. */
- private static boolean partialDataIsSuperset(
- @Nullable byte[] data1,
- @Nullable byte[] dataMask1,
- @Nullable byte[] data2,
- @Nullable byte[] dataMask2) {
- if (Arrays.equals(data1, data2) && Arrays.equals(dataMask1, dataMask2)) {
- return true;
- }
-
- if (data1 == null) {
- return true;
- }
-
- if (data2 == null) {
- return false;
- }
-
- // Mask2 should be at least as specific as mask1.
- if (dataMask1 != null && dataMask2 != null) {
- for (int i = 0, j = 0; i < dataMask1.length && j < dataMask2.length; i++, j++) {
- if ((dataMask1[i] & dataMask2[j]) != dataMask1[i]) {
- return false;
- }
- }
- }
-
- if (!matchesPartialData(data1, dataMask1, data2)) {
- return false;
- }
-
- return true;
- }
-
- /** Check if the uuid pattern is contained in a list of parcel uuids. */
- private static boolean matchesServiceUuids(
- @Nullable ParcelUuid uuid, @Nullable ParcelUuid parcelUuidMask,
- List uuids) {
- if (uuid == null) {
- // No service uuid filter has been set, so there's a match.
- return true;
- }
-
- UUID uuidMask = parcelUuidMask == null ? null : parcelUuidMask.getUuid();
- for (ParcelUuid parcelUuid : uuids) {
- if (matchesServiceUuid(uuid.getUuid(), uuidMask, parcelUuid.getUuid())) {
- return true;
- }
- }
- return false;
- }
-
- /** Check if the uuid pattern matches the particular service uuid. */
- private static boolean matchesServiceUuid(UUID uuid, @Nullable UUID mask, UUID data) {
- 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. Assumes that {@code data} and {@code
- * dataMask} have the same length.
- */
- /* package */
- static boolean matchesPartialData(
- @Nullable byte[] data, @Nullable byte[] dataMask, @Nullable byte[] parsedData) {
- if (data == null || parsedData == null || parsedData.length < data.length) {
- return false;
- }
- if (dataMask == null) {
- for (int i = 0; i < data.length; ++i) {
- if (parsedData[i] != data[i]) {
- return false;
- }
- }
- return true;
- }
- for (int i = 0; i < data.length; ++i) {
- if ((dataMask[i] & parsedData[i]) != (dataMask[i] & data[i])) {
- return false;
- }
- }
- return true;
- }
-
- @Override
- public String toString() {
- return "BleFilter [deviceName="
- + mDeviceName
- + ", deviceAddress="
- + mDeviceAddress
- + ", uuid="
- + mServiceUuid
- + ", uuidMask="
- + mServiceUuidMask
- + ", serviceDataUuid="
- + mServiceDataUuid
- + ", serviceData="
- + Arrays.toString(mServiceData)
- + ", serviceDataMask="
- + Arrays.toString(mServiceDataMask)
- + ", manufacturerId="
- + mManufacturerId
- + ", manufacturerData="
- + Arrays.toString(mManufacturerData)
- + ", manufacturerDataMask="
- + Arrays.toString(mManufacturerDataMask)
- + "]";
- }
-
- @Override
- public void writeToParcel(Parcel out, int flags) {
- out.writeString(mDeviceName);
- out.writeString(mDeviceAddress);
- out.writeInt(mManufacturerId);
- out.writeByteArray(mManufacturerData);
- out.writeByteArray(mManufacturerDataMask);
- out.writeParcelable(mServiceDataUuid, flags);
- out.writeByteArray(mServiceData);
- out.writeByteArray(mServiceDataMask);
- out.writeParcelable(mServiceUuid, flags);
- out.writeParcelable(mServiceUuidMask, flags);
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(
- mDeviceName,
- mDeviceAddress,
- mManufacturerId,
- Arrays.hashCode(mManufacturerData),
- Arrays.hashCode(mManufacturerDataMask),
- mServiceDataUuid,
- Arrays.hashCode(mServiceData),
- Arrays.hashCode(mServiceDataMask),
- mServiceUuid,
- mServiceUuidMask);
- }
-
- @Override
- public boolean equals(@Nullable Object obj) {
- if (this == obj) {
- return true;
- }
- if (obj == null || getClass() != obj.getClass()) {
- return false;
- }
- BleFilter other = (BleFilter) obj;
- return mDeviceName.equals(other.mDeviceName)
- && mDeviceAddress.equals(other.mDeviceAddress)
- && mManufacturerId == other.mManufacturerId
- && Arrays.equals(mManufacturerData, other.mManufacturerData)
- && Arrays.equals(mManufacturerDataMask, other.mManufacturerDataMask)
- && mServiceDataUuid.equals(other.mServiceDataUuid)
- && Arrays.equals(mServiceData, other.mServiceData)
- && Arrays.equals(mServiceDataMask, other.mServiceDataMask)
- && mServiceUuid.equals(other.mServiceUuid)
- && mServiceUuidMask.equals(other.mServiceUuidMask);
- }
-
- /** Builder class for {@link BleFilter}. */
- public static final class Builder {
-
- private String mDeviceName;
- private String mDeviceAddress;
-
- @Nullable
- private ParcelUuid mServiceUuid;
- @Nullable
- private ParcelUuid mUuidMask;
-
- private ParcelUuid mServiceDataUuid;
- @Nullable
- private byte[] mServiceData;
- @Nullable
- private byte[] mServiceDataMask;
-
- private int mManufacturerId = -1;
- private byte[] mManufacturerData;
- @Nullable
- private byte[] mManufacturerDataMask;
-
- /** Set filter on device name. */
- public Builder setDeviceName(String deviceName) {
- this.mDeviceName = deviceName;
- return this;
- }
-
- /**
- * Set filter on device address.
- *
- * @param deviceAddress The device Bluetooth address for the filter. It needs to be in the
- * format of "01:02:03:AB:CD:EF". The device address can be validated
- * using {@link
- * BluetoothAdapter#checkBluetoothAddress}.
- * @throws IllegalArgumentException If the {@code deviceAddress} is invalid.
- */
- public Builder setDeviceAddress(String deviceAddress) {
- if (!BluetoothAdapter.checkBluetoothAddress(deviceAddress)) {
- throw new IllegalArgumentException("invalid device address " + deviceAddress);
- }
- this.mDeviceAddress = deviceAddress;
- return this;
- }
-
- /** Set filter on service uuid. */
- public Builder setServiceUuid(@Nullable ParcelUuid serviceUuid) {
- this.mServiceUuid = serviceUuid;
- mUuidMask = null; // clear uuid mask
- return this;
- }
-
- /**
- * Set filter on partial service uuid. The {@code uuidMask} is the bit mask for the {@code
- * serviceUuid}. Set any bit in the mask to 1 to indicate a match is needed for the bit in
- * {@code serviceUuid}, and 0 to ignore that bit.
- *
- * @throws IllegalArgumentException If {@code serviceUuid} is {@code null} but {@code
- * uuidMask}
- * is not {@code null}.
- */
- public Builder setServiceUuid(@Nullable ParcelUuid serviceUuid,
- @Nullable ParcelUuid uuidMask) {
- if (uuidMask != null && serviceUuid == null) {
- throw new IllegalArgumentException("uuid is null while uuidMask is not null!");
- }
- this.mServiceUuid = serviceUuid;
- this.mUuidMask = uuidMask;
- return this;
- }
-
- /**
- * Set filtering on service data.
- */
- public Builder setServiceData(ParcelUuid serviceDataUuid, @Nullable byte[] serviceData) {
- this.mServiceDataUuid = serviceDataUuid;
- this.mServiceData = serviceData;
- mServiceDataMask = null; // clear service data mask
- return this;
- }
-
- /**
- * Set partial filter on service data. For any bit in the mask, set it to 1 if it needs to
- * match
- * the one in service data, otherwise set it to 0 to ignore that bit.
- *
- *
The {@code serviceDataMask} must have the same length of the {@code serviceData}.
- *
- * @throws IllegalArgumentException If {@code serviceDataMask} is {@code null} while {@code
- * serviceData} is not or {@code serviceDataMask} and
- * {@code serviceData} has different
- * length.
- */
- public Builder setServiceData(
- ParcelUuid serviceDataUuid,
- @Nullable byte[] serviceData,
- @Nullable byte[] serviceDataMask) {
- if (serviceDataMask != null) {
- if (serviceData == null) {
- throw new IllegalArgumentException(
- "serviceData is null while serviceDataMask is not null");
- }
- // Since the serviceDataMask is a bit mask for serviceData, the lengths of the two
- // byte array need to be the same.
- if (serviceData.length != serviceDataMask.length) {
- throw new IllegalArgumentException(
- "size mismatch for service data and service data mask");
- }
- }
- this.mServiceDataUuid = serviceDataUuid;
- this.mServiceData = serviceData;
- this.mServiceDataMask = serviceDataMask;
- return this;
- }
-
- /**
- * Set filter on on manufacturerData. A negative manufacturerId is considered as invalid id.
- *
- *
Note the first two bytes of the {@code manufacturerData} is the manufacturerId.
- *
- * @throws IllegalArgumentException If the {@code manufacturerId} is invalid.
- */
- public Builder setManufacturerData(int manufacturerId, @Nullable byte[] manufacturerData) {
- return setManufacturerData(manufacturerId, manufacturerData, null /* mask */);
- }
-
- /**
- * Set filter on partial manufacture data. For any bit in the mask, set it to 1 if it needs
- * to
- * match the one in manufacturer data, otherwise set it to 0.
- *
- *
The {@code manufacturerDataMask} must have the same length of {@code
- * manufacturerData}.
- *
- * @throws IllegalArgumentException If the {@code manufacturerId} is invalid, or {@code
- * manufacturerData} is null while {@code
- * manufacturerDataMask} is not, or {@code
- * manufacturerData} and {@code manufacturerDataMask} have
- * different length.
- */
- public Builder setManufacturerData(
- int manufacturerId,
- @Nullable byte[] manufacturerData,
- @Nullable byte[] manufacturerDataMask) {
- if (manufacturerData != null && manufacturerId < 0) {
- throw new IllegalArgumentException("invalid manufacture id");
- }
- if (manufacturerDataMask != null) {
- if (manufacturerData == null) {
- throw new IllegalArgumentException(
- "manufacturerData is null while manufacturerDataMask is not null");
- }
- // Since the manufacturerDataMask is a bit mask for manufacturerData, the lengths
- // of the two byte array need to be the same.
- if (manufacturerData.length != manufacturerDataMask.length) {
- throw new IllegalArgumentException(
- "size mismatch for manufacturerData and manufacturerDataMask");
- }
- }
- this.mManufacturerId = manufacturerId;
- this.mManufacturerData = manufacturerData == null ? new byte[0] : manufacturerData;
- this.mManufacturerDataMask = manufacturerDataMask;
- return this;
- }
-
-
- /**
- * Builds the filter.
- *
- * @throws IllegalArgumentException If the filter cannot be built.
- */
- public BleFilter build() {
- return new BleFilter(
- mDeviceName,
- mDeviceAddress,
- mServiceUuid,
- mUuidMask,
- mServiceDataUuid,
- mServiceData,
- mServiceDataMask,
- mManufacturerId,
- mManufacturerData,
- mManufacturerDataMask);
- }
- }
-
- /**
- * Changes ble filter to os filter
- */
- public ScanFilter toOsFilter() {
- ScanFilter.Builder osFilterBuilder = new ScanFilter.Builder();
- if (!TextUtils.isEmpty(getDeviceAddress())) {
- osFilterBuilder.setDeviceAddress(getDeviceAddress());
- }
- if (!TextUtils.isEmpty(getDeviceName())) {
- osFilterBuilder.setDeviceName(getDeviceName());
- }
-
- byte[] manufacturerData = getManufacturerData();
- if (getManufacturerId() != -1 && manufacturerData != null) {
- byte[] manufacturerDataMask = getManufacturerDataMask();
- if (manufacturerDataMask != null) {
- osFilterBuilder.setManufacturerData(
- getManufacturerId(), manufacturerData, manufacturerDataMask);
- } else {
- osFilterBuilder.setManufacturerData(getManufacturerId(), manufacturerData);
- }
- }
-
- ParcelUuid serviceDataUuid = getServiceDataUuid();
- byte[] serviceData = getServiceData();
- if (serviceDataUuid != null && serviceData != null) {
- byte[] serviceDataMask = getServiceDataMask();
- if (serviceDataMask != null) {
- osFilterBuilder.setServiceData(serviceDataUuid, serviceData, serviceDataMask);
- } else {
- osFilterBuilder.setServiceData(serviceDataUuid, serviceData);
- }
- }
-
- ParcelUuid serviceUuid = getServiceUuid();
- if (serviceUuid != null) {
- ParcelUuid serviceUuidMask = getServiceUuidMask();
- if (serviceUuidMask != null) {
- osFilterBuilder.setServiceUuid(serviceUuid, serviceUuidMask);
- } else {
- osFilterBuilder.setServiceUuid(serviceUuid);
- }
- }
- return osFilterBuilder.build();
- }
-}
diff --git a/nearby/service/java/com/android/server/nearby/common/ble/BleRecord.java b/nearby/service/java/com/android/server/nearby/common/ble/BleRecord.java
deleted file mode 100644
index 103a27fe8036812154510a8c6bcc3ddc3ed46540..0000000000000000000000000000000000000000
--- a/nearby/service/java/com/android/server/nearby/common/ble/BleRecord.java
+++ /dev/null
@@ -1,395 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.nearby.common.ble;
-
-import android.os.ParcelUuid;
-import android.util.Log;
-import android.util.SparseArray;
-
-import androidx.annotation.Nullable;
-
-import com.android.server.nearby.common.ble.util.StringUtils;
-
-import com.google.common.collect.ImmutableList;
-
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.UUID;
-
-/**
- * Represents a BLE record from Bluetooth LE scan.
- */
-public final class BleRecord {
-
- // The following data type values are assigned by Bluetooth SIG.
- // For more details refer to Bluetooth 4.1 specification, Volume 3, Part C, Section 18.
- private static final int DATA_TYPE_FLAGS = 0x01;
- private static final int DATA_TYPE_SERVICE_UUIDS_16_BIT_PARTIAL = 0x02;
- private static final int DATA_TYPE_SERVICE_UUIDS_16_BIT_COMPLETE = 0x03;
- private static final int DATA_TYPE_SERVICE_UUIDS_32_BIT_PARTIAL = 0x04;
- private static final int DATA_TYPE_SERVICE_UUIDS_32_BIT_COMPLETE = 0x05;
- private static final int DATA_TYPE_SERVICE_UUIDS_128_BIT_PARTIAL = 0x06;
- private static final int DATA_TYPE_SERVICE_UUIDS_128_BIT_COMPLETE = 0x07;
- private static final int DATA_TYPE_LOCAL_NAME_SHORT = 0x08;
- private static final int DATA_TYPE_LOCAL_NAME_COMPLETE = 0x09;
- private static final int DATA_TYPE_TX_POWER_LEVEL = 0x0A;
- private static final int DATA_TYPE_SERVICE_DATA = 0x16;
- private static final int DATA_TYPE_MANUFACTURER_SPECIFIC_DATA = 0xFF;
-
- /** The base 128-bit UUID representation of a 16-bit UUID. */
- private static final ParcelUuid BASE_UUID =
- ParcelUuid.fromString("00000000-0000-1000-8000-00805F9B34FB");
- /** Length of bytes for 16 bit UUID. */
- private static final int UUID_BYTES_16_BIT = 2;
- /** Length of bytes for 32 bit UUID. */
- private static final int UUID_BYTES_32_BIT = 4;
- /** Length of bytes for 128 bit UUID. */
- private static final int UUID_BYTES_128_BIT = 16;
-
- // Flags of the advertising data.
- // -1 when the scan record is not valid.
- private final int mAdvertiseFlags;
-
- private final ImmutableList mServiceUuids;
-
- // null when the scan record is not valid.
- @Nullable
- private final SparseArray mManufacturerSpecificData;
-
- // null when the scan record is not valid.
- @Nullable
- private final Map mServiceData;
-
- // Transmission power level(in dB).
- // Integer.MIN_VALUE when the scan record is not valid.
- private final int mTxPowerLevel;
-
- // Local name of the Bluetooth LE device.
- // null when the scan record is not valid.
- @Nullable
- private final String mDeviceName;
-
- // Raw bytes of scan record.
- // Never null, whether valid or not.
- private final byte[] mBytes;
-
- // If the raw scan record byte[] cannot be parsed, all non-primitive args here other than the
- // raw scan record byte[] and serviceUudis will be null. See parsefromBytes().
- private BleRecord(
- List serviceUuids,
- @Nullable SparseArray manufacturerData,
- @Nullable Map serviceData,
- int advertiseFlags,
- int txPowerLevel,
- @Nullable String deviceName,
- byte[] bytes) {
- this.mServiceUuids = ImmutableList.copyOf(serviceUuids);
- mManufacturerSpecificData = manufacturerData;
- this.mServiceData = serviceData;
- this.mDeviceName = deviceName;
- this.mAdvertiseFlags = advertiseFlags;
- this.mTxPowerLevel = txPowerLevel;
- this.mBytes = bytes;
- }
-
- /**
- * Returns a list of service UUIDs within the advertisement that are used to identify the
- * bluetooth GATT services.
- */
- public ImmutableList getServiceUuids() {
- return mServiceUuids;
- }
-
- /**
- * Returns a sparse array of manufacturer identifier and its corresponding manufacturer specific
- * data.
- */
- @Nullable
- public SparseArray getManufacturerSpecificData() {
- return mManufacturerSpecificData;
- }
-
- /**
- * Returns the manufacturer specific data associated with the manufacturer id. Returns {@code
- * null} if the {@code manufacturerId} is not found.
- */
- @Nullable
- public byte[] getManufacturerSpecificData(int manufacturerId) {
- if (mManufacturerSpecificData == null) {
- return null;
- }
- return mManufacturerSpecificData.get(manufacturerId);
- }
-
- /** Returns a map of service UUID and its corresponding service data. */
- @Nullable
- public Map getServiceData() {
- return mServiceData;
- }
-
- /**
- * Returns the service data byte array associated with the {@code serviceUuid}. Returns {@code
- * null} if the {@code serviceDataUuid} is not found.
- */
- @Nullable
- public byte[] getServiceData(ParcelUuid serviceDataUuid) {
- if (serviceDataUuid == null || mServiceData == null) {
- return null;
- }
- return mServiceData.get(serviceDataUuid);
- }
-
- /**
- * Returns the transmission power level of the packet in dBm. Returns {@link Integer#MIN_VALUE}
- * if
- * the field is not set. This value can be used to calculate the path loss of a received packet
- * using the following equation:
- *
- *
pathloss = txPowerLevel - rssi
- */
- public int getTxPowerLevel() {
- return mTxPowerLevel;
- }
-
- /** Returns the local name of the BLE device. The is a UTF-8 encoded string. */
- @Nullable
- public String getDeviceName() {
- return mDeviceName;
- }
-
- /** Returns raw bytes of scan record. */
- public byte[] getBytes() {
- return mBytes;
- }
-
- /**
- * Parse scan record bytes to {@link BleRecord}.
- *
- *
The format is defined in Bluetooth 4.1 specification, Volume 3, Part C, Section 11 and 18.
- *
- *
All numerical multi-byte entities and values shall use little-endian byte
- * order.
- *
- * @param scanRecord The scan record of Bluetooth LE advertisement and/or scan response.
- */
- public static BleRecord parseFromBytes(byte[] scanRecord) {
- int currentPos = 0;
- int advertiseFlag = -1;
- List serviceUuids = new ArrayList<>();
- String localName = null;
- int txPowerLevel = Integer.MIN_VALUE;
-
- SparseArray manufacturerData = new SparseArray<>();
- Map serviceData = new HashMap<>();
-
- try {
- while (currentPos < scanRecord.length) {
- // length is unsigned int.
- int length = scanRecord[currentPos++] & 0xFF;
- if (length == 0) {
- break;
- }
- // Note the length includes the length of the field type itself.
- int dataLength = length - 1;
- // fieldType is unsigned int.
- int fieldType = scanRecord[currentPos++] & 0xFF;
- switch (fieldType) {
- case DATA_TYPE_FLAGS:
- advertiseFlag = scanRecord[currentPos] & 0xFF;
- break;
- case DATA_TYPE_SERVICE_UUIDS_16_BIT_PARTIAL:
- case DATA_TYPE_SERVICE_UUIDS_16_BIT_COMPLETE:
- parseServiceUuid(scanRecord, currentPos, dataLength, UUID_BYTES_16_BIT,
- serviceUuids);
- break;
- case DATA_TYPE_SERVICE_UUIDS_32_BIT_PARTIAL:
- case DATA_TYPE_SERVICE_UUIDS_32_BIT_COMPLETE:
- parseServiceUuid(scanRecord, currentPos, dataLength, UUID_BYTES_32_BIT,
- serviceUuids);
- break;
- case DATA_TYPE_SERVICE_UUIDS_128_BIT_PARTIAL:
- case DATA_TYPE_SERVICE_UUIDS_128_BIT_COMPLETE:
- parseServiceUuid(scanRecord, currentPos, dataLength, UUID_BYTES_128_BIT,
- serviceUuids);
- break;
- case DATA_TYPE_LOCAL_NAME_SHORT:
- case DATA_TYPE_LOCAL_NAME_COMPLETE:
- localName = new String(extractBytes(scanRecord, currentPos, dataLength));
- break;
- case DATA_TYPE_TX_POWER_LEVEL:
- txPowerLevel = scanRecord[currentPos];
- break;
- case DATA_TYPE_SERVICE_DATA:
- // The first two bytes of the service data are service data UUID in little
- // endian. The rest bytes are service data.
- int serviceUuidLength = UUID_BYTES_16_BIT;
- byte[] serviceDataUuidBytes = extractBytes(scanRecord, currentPos,
- serviceUuidLength);
- ParcelUuid serviceDataUuid = parseUuidFrom(serviceDataUuidBytes);
- byte[] serviceDataArray =
- extractBytes(
- scanRecord, currentPos + serviceUuidLength,
- dataLength - serviceUuidLength);
- serviceData.put(serviceDataUuid, serviceDataArray);
- break;
- case DATA_TYPE_MANUFACTURER_SPECIFIC_DATA:
- // The first two bytes of the manufacturer specific data are
- // manufacturer ids in little endian.
- int manufacturerId =
- ((scanRecord[currentPos + 1] & 0xFF) << 8) + (scanRecord[currentPos]
- & 0xFF);
- byte[] manufacturerDataBytes = extractBytes(scanRecord, currentPos + 2,
- dataLength - 2);
- manufacturerData.put(manufacturerId, manufacturerDataBytes);
- break;
- default:
- // Just ignore, we don't handle such data type.
- break;
- }
- currentPos += dataLength;
- }
-
- return new BleRecord(
- serviceUuids,
- manufacturerData,
- serviceData,
- advertiseFlag,
- txPowerLevel,
- localName,
- scanRecord);
- } catch (Exception e) {
- Log.w("BleRecord", "Unable to parse scan record: " + Arrays.toString(scanRecord), e);
- // As the record is invalid, ignore all the parsed results for this packet
- // and return an empty record with raw scanRecord bytes in results
- // check at the top of this method does? Maybe we expect callers to use the
- // scanRecord part in
- // some fallback. But if that's the reason, it would seem we still can return null.
- // They still
- // have the raw scanRecord in hand, 'cause they passed it to us. It seems too easy for a
- // caller to misuse this "empty" BleRecord (as in b/22693067).
- return new BleRecord(ImmutableList.of(), null, null, -1, Integer.MIN_VALUE, null,
- scanRecord);
- }
- }
-
- // Parse service UUIDs.
- private static int parseServiceUuid(
- byte[] scanRecord,
- int currentPos,
- int dataLength,
- int uuidLength,
- List serviceUuids) {
- while (dataLength > 0) {
- byte[] uuidBytes = extractBytes(scanRecord, currentPos, uuidLength);
- serviceUuids.add(parseUuidFrom(uuidBytes));
- dataLength -= uuidLength;
- currentPos += uuidLength;
- }
- return currentPos;
- }
-
- // Helper method to extract bytes from byte array.
- private static byte[] extractBytes(byte[] scanRecord, int start, int length) {
- byte[] bytes = new byte[length];
- System.arraycopy(scanRecord, start, bytes, 0, length);
- return bytes;
- }
-
- @Override
- public String toString() {
- return "BleRecord [advertiseFlags="
- + mAdvertiseFlags
- + ", serviceUuids="
- + mServiceUuids
- + ", manufacturerSpecificData="
- + StringUtils.toString(mManufacturerSpecificData)
- + ", serviceData="
- + StringUtils.toString(mServiceData)
- + ", txPowerLevel="
- + mTxPowerLevel
- + ", deviceName="
- + mDeviceName
- + "]";
- }
-
- @Override
- public boolean equals(@Nullable Object obj) {
- if (obj == this) {
- return true;
- }
- if (!(obj instanceof BleRecord)) {
- return false;
- }
- BleRecord record = (BleRecord) obj;
- // BleRecord objects are built from bytes, so we only need that field.
- return Arrays.equals(mBytes, record.mBytes);
- }
-
- @Override
- public int hashCode() {
- // BleRecord objects are built from bytes, so we only need that field.
- return Arrays.hashCode(mBytes);
- }
-
- /**
- * Parse UUID from bytes. The {@code uuidBytes} can represent a 16-bit, 32-bit or 128-bit UUID,
- * but the returned UUID is always in 128-bit format. Note UUID is little endian in Bluetooth.
- *
- * @param uuidBytes Byte representation of uuid.
- * @return {@link ParcelUuid} parsed from bytes.
- * @throws IllegalArgumentException If the {@code uuidBytes} cannot be parsed.
- */
- private static ParcelUuid parseUuidFrom(byte[] uuidBytes) {
- if (uuidBytes == null) {
- throw new IllegalArgumentException("uuidBytes cannot be null");
- }
- int length = uuidBytes.length;
- if (length != UUID_BYTES_16_BIT
- && length != UUID_BYTES_32_BIT
- && length != UUID_BYTES_128_BIT) {
- throw new IllegalArgumentException("uuidBytes length invalid - " + length);
- }
- // Construct a 128 bit UUID.
- if (length == UUID_BYTES_128_BIT) {
- ByteBuffer buf = ByteBuffer.wrap(uuidBytes).order(ByteOrder.LITTLE_ENDIAN);
- long msb = buf.getLong(8);
- long lsb = buf.getLong(0);
- return new ParcelUuid(new UUID(msb, lsb));
- }
- // For 16 bit and 32 bit UUID we need to convert them to 128 bit value.
- // 128_bit_value = uuid * 2^96 + BASE_UUID
- long shortUuid;
- if (length == UUID_BYTES_16_BIT) {
- shortUuid = uuidBytes[0] & 0xFF;
- shortUuid += (uuidBytes[1] & 0xFF) << 8;
- } else {
- shortUuid = uuidBytes[0] & 0xFF;
- shortUuid += (uuidBytes[1] & 0xFF) << 8;
- shortUuid += (uuidBytes[2] & 0xFF) << 16;
- shortUuid += (uuidBytes[3] & 0xFF) << 24;
- }
- long msb = BASE_UUID.getUuid().getMostSignificantBits() + (shortUuid << 32);
- long lsb = BASE_UUID.getUuid().getLeastSignificantBits();
- return new ParcelUuid(new UUID(msb, lsb));
- }
-}
-
diff --git a/nearby/service/java/com/android/server/nearby/common/ble/BleSighting.java b/nearby/service/java/com/android/server/nearby/common/ble/BleSighting.java
deleted file mode 100644
index 71ec10cef1b27741e055db440a78db217e51f8e9..0000000000000000000000000000000000000000
--- a/nearby/service/java/com/android/server/nearby/common/ble/BleSighting.java
+++ /dev/null
@@ -1,215 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.nearby.common.ble;
-
-import android.bluetooth.BluetoothDevice;
-import android.bluetooth.le.ScanRecord;
-import android.bluetooth.le.ScanResult;
-import android.os.Build.VERSION_CODES;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import androidx.annotation.Nullable;
-import androidx.annotation.RequiresApi;
-import androidx.annotation.VisibleForTesting;
-
-import java.util.Arrays;
-import java.util.Objects;
-import java.util.concurrent.TimeUnit;
-
-/**
- * A sighting of a BLE device found in a Bluetooth LE scan.
- */
-
-public class BleSighting implements Parcelable {
-
- public static final Parcelable.Creator CREATOR = new Creator() {
- @Override
- public BleSighting createFromParcel(Parcel source) {
- BleSighting nBleSighting = new BleSighting(source.readParcelable(null),
- source.marshall(), source.readInt(), source.readLong());
- return null;
- }
-
- @Override
- public BleSighting[] newArray(int size) {
- return new BleSighting[size];
- }
- };
-
- // Max and min rssi value which is from {@link android.bluetooth.le.ScanResult#getRssi()}.
- @VisibleForTesting
- public static final int MAX_RSSI_VALUE = 126;
- @VisibleForTesting
- public static final int MIN_RSSI_VALUE = -127;
-
- /** Remote bluetooth device. */
- private final BluetoothDevice mDevice;
-
- /**
- * BLE record, including advertising data and response data. BleRecord is not parcelable, so
- * this
- * is created from bleRecordBytes.
- */
- private final BleRecord mBleRecord;
-
- /** The bytes of a BLE record. */
- private final byte[] mBleRecordBytes;
-
- /** Received signal strength. */
- private final int mRssi;
-
- /** Nanos timestamp when the ble device was observed (epoch time). */
- private final long mTimestampEpochNanos;
-
- /**
- * Constructor of a BLE sighting.
- *
- * @param device Remote bluetooth device that is found.
- * @param bleRecordBytes The bytes that will create a BleRecord.
- * @param rssi Received signal strength.
- * @param timestampEpochNanos Nanos timestamp when the BLE device was observed (epoch time).
- */
- public BleSighting(BluetoothDevice device, byte[] bleRecordBytes, int rssi,
- long timestampEpochNanos) {
- this.mDevice = device;
- this.mBleRecordBytes = bleRecordBytes;
- this.mRssi = rssi;
- this.mTimestampEpochNanos = timestampEpochNanos;
- mBleRecord = BleRecord.parseFromBytes(bleRecordBytes);
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- /** Returns the remote bluetooth device identified by the bluetooth device address. */
- public BluetoothDevice getDevice() {
- return mDevice;
- }
-
- /** Returns the BLE record, which is a combination of advertisement and scan response. */
- public BleRecord getBleRecord() {
- return mBleRecord;
- }
-
- /** Returns the bytes of the BLE record. */
- public byte[] getBleRecordBytes() {
- return mBleRecordBytes;
- }
-
- /** Returns the received signal strength in dBm. The valid range is [-127, 127]. */
- public int getRssi() {
- return mRssi;
- }
-
- /**
- * Returns the received signal strength normalized with the offset specific to the given device.
- * 3 is the rssi offset to calculate fast init distance.
- *
This method utilized the rssi offset maintained by Nearby Sharing.
- *
- * @return normalized rssi which is between [-127, 126] according to {@link
- * android.bluetooth.le.ScanResult#getRssi()}.
- */
- public int getNormalizedRSSI() {
- int adjustedRssi = mRssi + 3;
- if (adjustedRssi < MIN_RSSI_VALUE) {
- return MIN_RSSI_VALUE;
- } else if (adjustedRssi > MAX_RSSI_VALUE) {
- return MAX_RSSI_VALUE;
- } else {
- return adjustedRssi;
- }
- }
-
- /** Returns timestamp in epoch time when the scan record was observed. */
- public long getTimestampNanos() {
- return mTimestampEpochNanos;
- }
-
- /** Returns timestamp in epoch time when the scan record was observed, in millis. */
- public long getTimestampMillis() {
- return TimeUnit.NANOSECONDS.toMillis(mTimestampEpochNanos);
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeParcelable(mDevice, flags);
- dest.writeByteArray(mBleRecordBytes);
- dest.writeInt(mRssi);
- dest.writeLong(mTimestampEpochNanos);
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(mDevice, mRssi, mTimestampEpochNanos, Arrays.hashCode(mBleRecordBytes));
- }
-
- @Override
- public boolean equals(@Nullable Object obj) {
- if (this == obj) {
- return true;
- }
- if (!(obj instanceof BleSighting)) {
- return false;
- }
- BleSighting other = (BleSighting) obj;
- return Objects.equals(mDevice, other.mDevice)
- && mRssi == other.mRssi
- && Arrays.equals(mBleRecordBytes, other.mBleRecordBytes)
- && mTimestampEpochNanos == other.mTimestampEpochNanos;
- }
-
- @Override
- public String toString() {
- return "BleSighting{"
- + "device="
- + mDevice
- + ", bleRecord="
- + mBleRecord
- + ", rssi="
- + mRssi
- + ", timestampNanos="
- + mTimestampEpochNanos
- + "}";
- }
-
- /** Creates {@link BleSighting} using the {@link ScanResult}. */
- @RequiresApi(api = VERSION_CODES.LOLLIPOP)
- @Nullable
- public static BleSighting createFromOsScanResult(ScanResult osResult) {
- ScanRecord osScanRecord = osResult.getScanRecord();
- if (osScanRecord == null) {
- return null;
- }
-
- return new BleSighting(
- osResult.getDevice(),
- osScanRecord.getBytes(),
- osResult.getRssi(),
- // The timestamp from ScanResult is 'nanos since boot', Beacon lib will change it
- // as 'nanos
- // since epoch', but Nearby never reference this field, just pass it as 'nanos
- // since boot'.
- // ref to beacon/scan/impl/LBluetoothLeScannerCompat.fromOs for beacon design
- // about how to
- // convert nanos since boot to epoch.
- osResult.getTimestampNanos());
- }
-}
-
diff --git a/nearby/service/java/com/android/server/nearby/common/ble/decode/BeaconDecoder.java b/nearby/service/java/com/android/server/nearby/common/ble/decode/BeaconDecoder.java
deleted file mode 100644
index 9e795ac7a1c26db224b7af4abb4f56160015744d..0000000000000000000000000000000000000000
--- a/nearby/service/java/com/android/server/nearby/common/ble/decode/BeaconDecoder.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.nearby.common.ble.decode;
-
-import androidx.annotation.Nullable;
-
-import com.android.server.nearby.common.ble.BleRecord;
-
-/**
- * This class encapsulates the logic specific to each manufacturer for parsing formats for beacons,
- * and presents a common API to access important ADV/EIR packet fields such as:
- *
- *
- *
UUID (universally unique identifier), a value uniquely identifying a group of one or
- * more beacons as belonging to an organization or of a certain type, up to 128 bits.
- *
Instance a 32-bit unsigned integer that can be used to group related beacons that
- * have the same UUID.
- *
the mathematics of TX signal strength, used for proximity calculations.
- *
- *
- * ...and others.
- *
- * @see BLE Glossary
- * @see Bluetooth
- * Data Types Specification
- */
-public abstract class BeaconDecoder {
- /**
- * Returns true if the bleRecord corresponds to a beacon format that contains sufficient
- * information to construct a BeaconId and contains the Tx power.
- */
- public boolean supportsBeaconIdAndTxPower(@SuppressWarnings("unused") BleRecord bleRecord) {
- return true;
- }
-
- /**
- * Returns true if this decoder supports returning TxPower via {@link
- * #getCalibratedBeaconTxPower(BleRecord)}.
- */
- public boolean supportsTxPower() {
- return true;
- }
-
- /**
- * Reads the calibrated transmitted power at 1 meter of the beacon in dBm. This value is
- * contained
- * in the scan record, as set by the transmitting beacon. Suitable for use in computing path
- * loss,
- * distance, and related derived values.
- *
- * @param bleRecord the parsed payload contained in the beacon packet
- * @return integer value of the calibrated Tx power in dBm or null if the bleRecord doesn't
- * contain sufficient information to calculate the Tx power.
- */
- @Nullable
- public abstract Integer getCalibratedBeaconTxPower(BleRecord bleRecord);
-
- /**
- * Extract telemetry information from the beacon. Byte 0 of the returned telemetry block should
- * encode the telemetry format.
- *
- * @return telemetry block for this beacon, or null if no telemetry data is found in the scan
- * record.
- */
- @Nullable
- public byte[] getTelemetry(@SuppressWarnings("unused") BleRecord bleRecord) {
- return null;
- }
-
- /** Returns the appropriate type for this scan record. */
- public abstract int getBeaconIdType();
-
- /**
- * Returns an array of bytes which uniquely identify this beacon, for beacons from any of the
- * supported beacon types. This unique identifier is the indexing key for various internal
- * services. Returns null if the bleRecord doesn't contain sufficient information to construct
- * the
- * ID.
- */
- @Nullable
- public abstract byte[] getBeaconIdBytes(BleRecord bleRecord);
-
- /**
- * Returns the URL of the beacon. Returns null if the bleRecord doesn't contain a URL or
- * contains
- * a malformed URL.
- */
- @Nullable
- public String getUrl(BleRecord bleRecord) {
- return null;
- }
-}
diff --git a/nearby/service/java/com/android/server/nearby/common/ble/decode/FastPairDecoder.java b/nearby/service/java/com/android/server/nearby/common/ble/decode/FastPairDecoder.java
deleted file mode 100644
index c1ff9fd31e7c9c681adfecb241fcaab2d7f494a3..0000000000000000000000000000000000000000
--- a/nearby/service/java/com/android/server/nearby/common/ble/decode/FastPairDecoder.java
+++ /dev/null
@@ -1,297 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.nearby.common.ble.decode;
-
-import android.bluetooth.le.ScanRecord;
-import android.os.ParcelUuid;
-import android.util.Log;
-import android.util.SparseArray;
-
-import androidx.annotation.Nullable;
-
-import com.android.server.nearby.common.ble.BleFilter;
-import com.android.server.nearby.common.ble.BleRecord;
-
-import java.util.Arrays;
-
-/**
- * Parses Fast Pair information out of {@link BleRecord}s.
- *
- *
There are 2 different packet formats that are supported, which is used can be determined by
- * packet length:
- *
- *
For 3-byte packets, the full packet is the model ID.
- *
- *
For all other packets, the first byte is the header, followed by the model ID, followed by
- * zero or more extra fields. Each field has its own header byte followed by the field value. The
- * packet header is formatted as 0bVVVLLLLR (V = version, L = model ID length, R = reserved) and
- * each extra field header is 0bLLLLTTTT (L = field length, T = field type).
- *
- * @see go/fast-pair-2-service-data
- */
-public class FastPairDecoder extends BeaconDecoder {
-
- private static final int FIELD_TYPE_BLOOM_FILTER = 0;
- private static final int FIELD_TYPE_BLOOM_FILTER_SALT = 1;
- private static final int FIELD_TYPE_BLOOM_FILTER_NO_NOTIFICATION = 2;
- private static final int FIELD_TYPE_BATTERY = 3;
- private static final int FIELD_TYPE_BATTERY_NO_NOTIFICATION = 4;
- public static final int FIELD_TYPE_CONNECTION_STATE = 5;
- private static final int FIELD_TYPE_RANDOM_RESOLVABLE_DATA = 6;
-
- /** FE2C is the 16-bit Service UUID. The rest is the base UUID. See BluetoothUuid (hidden). */
- private static final ParcelUuid FAST_PAIR_SERVICE_PARCEL_UUID =
- ParcelUuid.fromString("0000FE2C-0000-1000-8000-00805F9B34FB");
-
- /** The filter you use to scan for Fast Pair BLE advertisements. */
- public static final BleFilter FILTER =
- new BleFilter.Builder().setServiceData(FAST_PAIR_SERVICE_PARCEL_UUID,
- new byte[0]).build();
-
- // NOTE: Ensure that all bitmasks are always ints, not bytes so that bitshifting works correctly
- // without needing worry about signing errors.
- private static final int HEADER_VERSION_BITMASK = 0b11100000;
- private static final int HEADER_LENGTH_BITMASK = 0b00011110;
- private static final int HEADER_VERSION_OFFSET = 5;
- private static final int HEADER_LENGTH_OFFSET = 1;
-
- private static final int EXTRA_FIELD_LENGTH_BITMASK = 0b11110000;
- private static final int EXTRA_FIELD_TYPE_BITMASK = 0b00001111;
- private static final int EXTRA_FIELD_LENGTH_OFFSET = 4;
- private static final int EXTRA_FIELD_TYPE_OFFSET = 0;
-
- private static final int MIN_ID_LENGTH = 3;
- private static final int MAX_ID_LENGTH = 14;
- private static final int HEADER_INDEX = 0;
- private static final int HEADER_LENGTH = 1;
- private static final int FIELD_HEADER_LENGTH = 1;
-
- // Not using java.util.IllegalFormatException because it is unchecked.
- private static class IllegalFormatException extends Exception {
- private IllegalFormatException(String message) {
- super(message);
- }
- }
-
- @Nullable
- @Override
- public Integer getCalibratedBeaconTxPower(BleRecord bleRecord) {
- return null;
- }
-
- // TODO(b/205320613) create beacon type
- @Override
- public int getBeaconIdType() {
- return 1;
- }
-
- /** Returns the Model ID from our service data, if present. */
- @Nullable
- @Override
- public byte[] getBeaconIdBytes(BleRecord bleRecord) {
- return getModelId(bleRecord.getServiceData(FAST_PAIR_SERVICE_PARCEL_UUID));
- }
-
- /** Returns the Model ID from our service data, if present. */
- @Nullable
- public static byte[] getModelId(@Nullable byte[] serviceData) {
- if (serviceData == null) {
- return null;
- }
-
- if (serviceData.length >= MIN_ID_LENGTH) {
- if (serviceData.length == MIN_ID_LENGTH) {
- // If the length == 3, all bytes are the ID. See flag docs for more about
- // endianness.
- return serviceData;
- } else {
- // Otherwise, the first byte is a header which contains the length of the
- // big-endian model
- // ID that follows. The model ID will be trimmed if it contains leading zeros.
- int idIndex = 1;
- int end = idIndex + getIdLength(serviceData);
- while (serviceData[idIndex] == 0 && end - idIndex > MIN_ID_LENGTH) {
- idIndex++;
- }
- return Arrays.copyOfRange(serviceData, idIndex, end);
- }
- }
- return null;
- }
-
- /** Gets the FastPair service data array if available, otherwise returns null. */
- @Nullable
- public static byte[] getServiceDataArray(BleRecord bleRecord) {
- return bleRecord.getServiceData(FAST_PAIR_SERVICE_PARCEL_UUID);
- }
-
- /** Gets the FastPair service data array if available, otherwise returns null. */
- @Nullable
- public static byte[] getServiceDataArray(ScanRecord scanRecord) {
- return scanRecord.getServiceData(FAST_PAIR_SERVICE_PARCEL_UUID);
- }
-
- /** Gets the bloom filter from the extra fields if available, otherwise returns null. */
- @Nullable
- public static byte[] getBloomFilter(@Nullable byte[] serviceData) {
- return getExtraField(serviceData, FIELD_TYPE_BLOOM_FILTER);
- }
-
- /** Gets the bloom filter salt from the extra fields if available, otherwise returns null. */
- @Nullable
- public static byte[] getBloomFilterSalt(byte[] serviceData) {
- return getExtraField(serviceData, FIELD_TYPE_BLOOM_FILTER_SALT);
- }
-
- /**
- * Gets the suppress notification with bloom filter from the extra fields if available,
- * otherwise
- * returns null.
- */
- @Nullable
- public static byte[] getBloomFilterNoNotification(@Nullable byte[] serviceData) {
- return getExtraField(serviceData, FIELD_TYPE_BLOOM_FILTER_NO_NOTIFICATION);
- }
-
- /** Gets the battery level from extra fields if available, otherwise return null. */
- @Nullable
- public static byte[] getBatteryLevel(byte[] serviceData) {
- return getExtraField(serviceData, FIELD_TYPE_BATTERY);
- }
-
- /**
- * Gets the suppress notification with battery level from extra fields if available, otherwise
- * return null.
- */
- @Nullable
- public static byte[] getBatteryLevelNoNotification(byte[] serviceData) {
- return getExtraField(serviceData, FIELD_TYPE_BATTERY_NO_NOTIFICATION);
- }
-
- /**
- * Gets the random resolvable data from extra fields if available, otherwise
- * return null.
- */
- @Nullable
- public static byte[] getRandomResolvableData(byte[] serviceData) {
- return getExtraField(serviceData, FIELD_TYPE_RANDOM_RESOLVABLE_DATA);
- }
-
- @Nullable
- private static byte[] getExtraField(@Nullable byte[] serviceData, int fieldId) {
- if (serviceData == null || serviceData.length < HEADER_INDEX + HEADER_LENGTH) {
- return null;
- }
- try {
- return getExtraFields(serviceData).get(fieldId);
- } catch (IllegalFormatException e) {
- Log.v("FastPairDecode", "Extra fields incorrectly formatted.");
- return null;
- }
- }
-
- /** Gets extra field data at the end of the packet, defined by the extra field header. */
- private static SparseArray getExtraFields(byte[] serviceData)
- throws IllegalFormatException {
- SparseArray extraFields = new SparseArray<>();
- if (getVersion(serviceData) != 0) {
- return extraFields;
- }
- int headerIndex = getFirstExtraFieldHeaderIndex(serviceData);
- while (headerIndex < serviceData.length) {
- int length = getExtraFieldLength(serviceData, headerIndex);
- int index = headerIndex + FIELD_HEADER_LENGTH;
- int type = getExtraFieldType(serviceData, headerIndex);
- int end = index + length;
- if (extraFields.get(type) == null) {
- if (end <= serviceData.length) {
- extraFields.put(type, Arrays.copyOfRange(serviceData, index, end));
- } else {
- throw new IllegalFormatException(
- "Invalid length, " + end + " is longer than service data size "
- + serviceData.length);
- }
- }
- headerIndex = end;
- }
- return extraFields;
- }
-
- /** Checks whether or not a valid ID is included in the service data packet. */
- public static boolean hasBeaconIdBytes(BleRecord bleRecord) {
- byte[] serviceData = bleRecord.getServiceData(FAST_PAIR_SERVICE_PARCEL_UUID);
- return checkModelId(serviceData);
- }
-
- /** Check whether byte array is FastPair model id or not. */
- public static boolean checkModelId(@Nullable byte[] scanResult) {
- return scanResult != null
- // The 3-byte format has no header byte (all bytes are the ID).
- && (scanResult.length == MIN_ID_LENGTH
- // Header byte exists. We support only format version 0. (A different version
- // indicates
- // a breaking change in the format.)
- || (scanResult.length > MIN_ID_LENGTH
- && getVersion(scanResult) == 0
- && isIdLengthValid(scanResult)));
- }
-
- /** Checks whether or not bloom filter is included in the service data packet. */
- public static boolean hasBloomFilter(BleRecord bleRecord) {
- return (getBloomFilter(getServiceDataArray(bleRecord)) != null
- || getBloomFilterNoNotification(getServiceDataArray(bleRecord)) != null);
- }
-
- /** Checks whether or not bloom filter is included in the service data packet. */
- public static boolean hasBloomFilter(ScanRecord scanRecord) {
- return (getBloomFilter(getServiceDataArray(scanRecord)) != null
- || getBloomFilterNoNotification(getServiceDataArray(scanRecord)) != null);
- }
-
- private static int getVersion(byte[] serviceData) {
- return serviceData.length == MIN_ID_LENGTH
- ? 0
- : (serviceData[HEADER_INDEX] & HEADER_VERSION_BITMASK) >> HEADER_VERSION_OFFSET;
- }
-
- private static int getIdLength(byte[] serviceData) {
- return serviceData.length == MIN_ID_LENGTH
- ? MIN_ID_LENGTH
- : (serviceData[HEADER_INDEX] & HEADER_LENGTH_BITMASK) >> HEADER_LENGTH_OFFSET;
- }
-
- private static int getFirstExtraFieldHeaderIndex(byte[] serviceData) {
- return HEADER_INDEX + HEADER_LENGTH + getIdLength(serviceData);
- }
-
- private static int getExtraFieldLength(byte[] serviceData, int extraFieldIndex) {
- return (serviceData[extraFieldIndex] & EXTRA_FIELD_LENGTH_BITMASK)
- >> EXTRA_FIELD_LENGTH_OFFSET;
- }
-
- private static int getExtraFieldType(byte[] serviceData, int extraFieldIndex) {
- return (serviceData[extraFieldIndex] & EXTRA_FIELD_TYPE_BITMASK) >> EXTRA_FIELD_TYPE_OFFSET;
- }
-
- private static boolean isIdLengthValid(byte[] serviceData) {
- int idLength = getIdLength(serviceData);
- return MIN_ID_LENGTH <= idLength
- && idLength <= MAX_ID_LENGTH
- && idLength + HEADER_LENGTH <= serviceData.length;
- }
-}
-
diff --git a/nearby/service/java/com/android/server/nearby/common/ble/testing/FastPairTestData.java b/nearby/service/java/com/android/server/nearby/common/ble/testing/FastPairTestData.java
deleted file mode 100644
index f27899f3e91608122d16d90d9c997b24a318aa75..0000000000000000000000000000000000000000
--- a/nearby/service/java/com/android/server/nearby/common/ble/testing/FastPairTestData.java
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.nearby.common.ble.testing;
-
-import com.android.server.nearby.util.ArrayUtils;
-import com.android.server.nearby.util.Hex;
-
-/**
- * Test class to provide example to unit test.
- */
-public class FastPairTestData {
- private static final byte[] FAST_PAIR_RECORD_BIG_ENDIAN =
- Hex.stringToBytes("02011E020AF006162CFEAABBCC");
-
- /**
- * A Fast Pair frame, Note: The service UUID is FE2C, but in the
- * packet it's 2CFE, since the core Bluetooth data types are little-endian.
- *
- *
However, the model ID is big-endian (multi-byte values in our spec are now big-endian, aka
- * network byte order).
- *
- * @see {http://go/fast-pair-service-data}
- */
- public static byte[] getFastPairRecord() {
- return FAST_PAIR_RECORD_BIG_ENDIAN;
- }
-
- /** A Fast Pair frame, with a shared account key. */
- public static final byte[] FAST_PAIR_SHARED_ACCOUNT_KEY_RECORD =
- Hex.stringToBytes("02011E020AF00C162CFE007011223344556677");
-
- /** Model ID in {@link #getFastPairRecord()}. */
- public static final byte[] FAST_PAIR_MODEL_ID = Hex.stringToBytes("AABBCC");
-
- /** @see #getFastPairRecord() */
- public static byte[] newFastPairRecord(byte header, byte[] modelId) {
- return newFastPairRecord(
- modelId.length == 3 ? modelId : ArrayUtils.concatByteArrays(new byte[] {header},
- modelId));
- }
-
- /** @see #getFastPairRecord() */
- public static byte[] newFastPairRecord(byte[] serviceData) {
- int length = /* length of type and service UUID = */ 3 + serviceData.length;
- return Hex.stringToBytes(
- String.format("02011E020AF0%02X162CFE%s", length,
- Hex.bytesToStringUppercase(serviceData)));
- }
-
- // This is an example of advertising data with AD types
- public static byte[] adv_1 = {
- 0x02, // Length of this Data
- 0x01, // <>
- 0x01, // LE Limited Discoverable Mode
- 0x0A, // Length of this Data
- 0x09, // <>
- 'P', 'e', 'd', 'o', 'm', 'e', 't', 'e', 'r'
- };
-
- // This is an example of advertising data with positive TX Power
- // Level.
- public static byte[] adv_2 = {
- 0x02, // Length of this Data
- 0x0a, // <>
- 127 // Level = 127
- };
-
- // Example data including a service data block
- public static byte[] sd1 = {
- 0x02, // Length of this Data
- 0x01, // <>
- 0x04, // BR/EDR Not Supported.
- 0x03, // Length of this Data
- 0x02, // <>
- 0x04,
- 0x18, // TX Power Service UUID
- 0x1e, // Length of this Data
- (byte) 0x16, // <>
- // Service UUID
- (byte) 0xe0,
- 0x00,
- // gBeacon Header
- 0x15,
- // Running time ENCRYPT
- (byte) 0xd2,
- 0x77,
- 0x01,
- 0x00,
- // Scan Freq ENCRYPT
- 0x32,
- 0x05,
- // Time in slow mode
- 0x00,
- 0x00,
- // Time in fast mode
- 0x7f,
- 0x17,
- // Subset of UID
- 0x56,
- 0x00,
- // ID Mask
- (byte) 0xd4,
- 0x7c,
- 0x18,
- // RFU (reserved)
- 0x00,
- // GUID = decimal 1297482358
- 0x76,
- 0x02,
- 0x56,
- 0x4d,
- 0x00,
- // Ranging Payload Header
- 0x24,
- // MAC of scanning address
- (byte) 0xa4,
- (byte) 0xbb,
- // NORM RX RSSI -67dBm
- (byte) 0xb0,
- // NORM TX POWER -77dBm, so actual TX POWER = -36dBm
- (byte) 0xb3,
- // Note based on the values aboves PATH LOSS = (-36) - (-67) = 31dBm
- // Below zero padding added to test it is handled correctly
- 0x00
- };
-
-}
diff --git a/nearby/service/java/com/android/server/nearby/common/ble/util/RangingUtils.java b/nearby/service/java/com/android/server/nearby/common/ble/util/RangingUtils.java
deleted file mode 100644
index eec52ad14d50e81335142a840c24e248454e6354..0000000000000000000000000000000000000000
--- a/nearby/service/java/com/android/server/nearby/common/ble/util/RangingUtils.java
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.nearby.common.ble.util;
-
-
-/**
- * Ranging utilities embody the physics of converting RF path loss to distance. The free space path
- * loss is proportional to the square of the distance from transmitter to receiver, and to the
- * square of the frequency of the propagation signal.
- */
-public final class RangingUtils {
- private static final int MAX_RSSI_VALUE = 126;
- private static final int MIN_RSSI_VALUE = -127;
-
- private RangingUtils() {
- }
-
- /* This was original derived in {@link com.google.android.gms.beacon.util.RangingUtils} from
- * Free-space_path_loss.
- * Duplicated here for easy reference.
- *
- * c = speed of light (2.9979 x 10^8 m/s);
- * f = frequency (Bluetooth center frequency is 2.44175GHz = 2.44175x10^9 Hz);
- * l = wavelength (in meters);
- * d = distance (from transmitter to receiver in meters);
- * dB = decibels
- * dBm = decibel milliwatts
- *
- *
- * Free-space path loss (FSPL) is proportional to the square of the distance between the
- * transmitter and the receiver, and also proportional to the square of the frequency of the
- * radio signal.
- *
- * FSPL = (4 * pi * d / l)^2 = (4 * pi * d * f / c)^2
- *
- * FSPL (dB) = 10 * log10((4 * pi * d * f / c)^2)
- * = 20 * log10(4 * pi * d * f / c)
- * = (20 * log10(d)) + (20 * log10(f)) + (20 * log10(4 * pi/c))
- *
- * Calculating constants:
- *
- * FSPL_FREQ = 20 * log10(f)
- * = 20 * log10(2.44175 * 10^9)
- * = 187.75
- *
- * FSPL_LIGHT = 20 * log10(4 * pi/c)
- * = 20 * log10(4 * pi/(2.9979 * 10^8))
- * = 20 * log10(4 * pi/(2.9979 * 10^8))
- * = 20 * log10(41.9172441s * 10^-9)
- * = -147.55
- *
- * FSPL_DISTANCE_1M = 20 * log10(1)
- * = 0
- *
- * PATH_LOSS_AT_1M = FSPL_DISTANCE_1M + FSPL_FREQ + FSPL_LIGHT
- * = 0 + 187.75 + (-147.55)
- * = 40.20db [round to 41db]
- *
- * Note: Rounding up makes us "closer" and makes us more aggressive at showing notifications.
- */
- private static final int RSSI_DROP_OFF_AT_1_M = 41;
-
- /**
- * Convert target distance and txPower to a RSSI value using the Log-distance path loss model
- * with Path Loss at 1m of 41db.
- *
- * @return RSSI expected at distanceInMeters with device broadcasting at txPower.
- */
- public static int rssiFromTargetDistance(double distanceInMeters, int txPower) {
- /*
- * See
- * Log-distance path loss model.
- *
- * PL = total path loss in db
- * txPower = TxPower in dbm
- * rssi = Received signal strength in dbm
- * PL_0 = Path loss at reference distance d_0 {@link RSSI_DROP_OFF_AT_1_M} dbm
- * d = length of path
- * d_0 = reference distance (1 m)
- * gamma = path loss exponent (2 in free space)
- *
- * Log-distance path loss (LDPL) formula:
- *
- * PL = txPower - rssi = PL_0 + 10 * gamma * log_10(d / d_0)
- * txPower - rssi = RSSI_DROP_OFF_AT_1_M + 10 * 2 * log_10
- * (distanceInMeters / 1)
- * - rssi = -txPower + RSSI_DROP_OFF_AT_1_M + 20 * log_10(distanceInMeters)
- * rssi = txPower - RSSI_DROP_OFF_AT_1_M - 20 * log_10(distanceInMeters)
- */
- txPower = adjustPower(txPower);
- return distanceInMeters == 0
- ? txPower
- : (int) Math.floor((txPower - RSSI_DROP_OFF_AT_1_M)
- - 20 * Math.log10(distanceInMeters));
- }
-
- /**
- * Convert RSSI and txPower to a distance value using the Log-distance path loss model with Path
- * Loss at 1m of 41db.
- *
- * @return distance in meters with device broadcasting at txPower and given RSSI.
- */
- public static double distanceFromRssiAndTxPower(int rssi, int txPower) {
- /*
- * See Log-distance
- * path
- * loss model.
- *
- * PL = total path loss in db
- * txPower = TxPower in dbm
- * rssi = Received signal strength in dbm
- * PL_0 = Path loss at reference distance d_0 {@link RSSI_DROP_OFF_AT_1_M} dbm
- * d = length of path
- * d_0 = reference distance (1 m)
- * gamma = path loss exponent (2 in free space)
- *
- * Log-distance path loss (LDPL) formula:
- *
- * PL = txPower - rssi = PL_0 + 10 * gamma * log_10(d /
- * d_0)
- * txPower - rssi = RSSI_DROP_OFF_AT_1_M + 10 * gamma * log_10(d /
- * d_0)
- * txPower - rssi - RSSI_DROP_OFF_AT_1_M = 10 * 2 * log_10
- * (distanceInMeters / 1)
- * txPower - rssi - RSSI_DROP_OFF_AT_1_M = 20 * log_10(distanceInMeters / 1)
- * (txPower - rssi - RSSI_DROP_OFF_AT_1_M) / 20 = log_10(distanceInMeters)
- * 10 ^ ((txPower - rssi - RSSI_DROP_OFF_AT_1_M) / 20) = distanceInMeters
- */
- txPower = adjustPower(txPower);
- rssi = adjustPower(rssi);
- return Math.pow(10, (txPower - rssi - RSSI_DROP_OFF_AT_1_M) / 20.0);
- }
-
- /**
- * Prevents the power from becoming too large or too small.
- */
- private static int adjustPower(int power) {
- if (power > MAX_RSSI_VALUE) {
- return MAX_RSSI_VALUE;
- }
- if (power < MIN_RSSI_VALUE) {
- return MIN_RSSI_VALUE;
- }
- return power;
- }
-}
-
diff --git a/nearby/service/java/com/android/server/nearby/common/ble/util/StringUtils.java b/nearby/service/java/com/android/server/nearby/common/ble/util/StringUtils.java
deleted file mode 100644
index 4d90b6d554388456144fac2f67d55903fe7e5f20..0000000000000000000000000000000000000000
--- a/nearby/service/java/com/android/server/nearby/common/ble/util/StringUtils.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.nearby.common.ble.util;
-
-import android.annotation.Nullable;
-import android.util.SparseArray;
-
-import java.util.Arrays;
-import java.util.Iterator;
-import java.util.Map;
-
-/** Helper class for Bluetooth LE utils. */
-public final class StringUtils {
- private StringUtils() {
- }
-
- /** Returns a string composed from a {@link SparseArray}. */
- public static String toString(@Nullable SparseArray array) {
- if (array == null) {
- return "null";
- }
- if (array.size() == 0) {
- return "{}";
- }
- StringBuilder buffer = new StringBuilder();
- buffer.append('{');
- for (int i = 0; i < array.size(); ++i) {
- buffer.append(array.keyAt(i)).append("=").append(Arrays.toString(array.valueAt(i)));
- }
- buffer.append('}');
- return buffer.toString();
- }
-
- /** Returns a string composed from a {@link Map}. */
- public static String toString(@Nullable Map map) {
- if (map == null) {
- return "null";
- }
- if (map.isEmpty()) {
- return "{}";
- }
- StringBuilder buffer = new StringBuilder();
- buffer.append('{');
- Iterator> it = map.entrySet().iterator();
- while (it.hasNext()) {
- Map.Entry entry = it.next();
- Object key = entry.getKey();
- buffer.append(key).append("=").append(Arrays.toString(map.get(key)));
- if (it.hasNext()) {
- buffer.append(", ");
- }
- }
- buffer.append('}');
- return buffer.toString();
- }
-}
diff --git a/nearby/service/java/com/android/server/nearby/common/bloomfilter/BloomFilter.java b/nearby/service/java/com/android/server/nearby/common/bloomfilter/BloomFilter.java
deleted file mode 100644
index 6d4275f94350441fef51fc3fc27b38dcbbf5aa39..0000000000000000000000000000000000000000
--- a/nearby/service/java/com/android/server/nearby/common/bloomfilter/BloomFilter.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.nearby.common.bloomfilter;
-
-import static java.nio.charset.StandardCharsets.UTF_8;
-
-import com.google.common.primitives.UnsignedInts;
-
-import java.nio.charset.Charset;
-import java.util.Arrays;
-import java.util.BitSet;
-
-/**
- * A bloom filter that gives access to the underlying BitSet.
- */
-public class BloomFilter {
- private static final Charset CHARSET = UTF_8;
-
- /**
- * Receives a value and converts it into an array of ints that will be converted to indexes for
- * the filter.
- */
- public interface Hasher {
- /**
- * Generate hash value.
- */
- int[] getHashes(byte[] value);
- }
-
- // The backing data for this bloom filter. As additions are made, they're OR'd until it
- // eventually reaches 0xFF.
- private final BitSet mBits;
- // The max length of bits.
- private final int mBitLength;
- // The hasher to use for converting a value into an array of hashes.
- private final Hasher mHasher;
-
- public BloomFilter(byte[] bytes, Hasher hasher) {
- this.mBits = BitSet.valueOf(bytes);
- this.mBitLength = bytes.length * 8;
- this.mHasher = hasher;
- }
-
- /**
- * Return the bloom filter check bit set as byte array.
- */
- public byte[] asBytes() {
- // BitSet.toByteArray() truncates all the unset bits after the last set bit (eg. [0,0,1,0]
- // becomes [0,0,1]) so we re-add those bytes if needed with Arrays.copy().
- byte[] b = mBits.toByteArray();
- if (b.length == mBitLength / 8) {
- return b;
- }
- return Arrays.copyOf(b, mBitLength / 8);
- }
-
- /**
- * Add string value to bloom filter hash.
- */
- public void add(String s) {
- add(s.getBytes(CHARSET));
- }
-
- /**
- * Adds value to bloom filter hash.
- */
- public void add(byte[] value) {
- int[] hashes = mHasher.getHashes(value);
- for (int hash : hashes) {
- mBits.set(UnsignedInts.remainder(hash, mBitLength));
- }
- }
-
- /**
- * Check if the string format has collision.
- */
- public boolean possiblyContains(String s) {
- return possiblyContains(s.getBytes(CHARSET));
- }
-
- /**
- * Checks if value after hash will have collision.
- */
- public boolean possiblyContains(byte[] value) {
- int[] hashes = mHasher.getHashes(value);
- for (int hash : hashes) {
- if (!mBits.get(UnsignedInts.remainder(hash, mBitLength))) {
- return false;
- }
- }
- return true;
- }
-}
-
diff --git a/nearby/service/java/com/android/server/nearby/common/bloomfilter/FastPairBloomFilterHasher.java b/nearby/service/java/com/android/server/nearby/common/bloomfilter/FastPairBloomFilterHasher.java
deleted file mode 100644
index 0ccee97255b3aef61097e85f41a7344aa88bea7c..0000000000000000000000000000000000000000
--- a/nearby/service/java/com/android/server/nearby/common/bloomfilter/FastPairBloomFilterHasher.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.nearby.common.bloomfilter;
-
-import com.google.common.hash.Hashing;
-
-import java.nio.ByteBuffer;
-
-/**
- * Hasher which hashes a value using SHA-256 and splits it into parts, each of which can be
- * converted to an index.
- */
-public class FastPairBloomFilterHasher implements BloomFilter.Hasher {
-
- private static final int NUM_INDEXES = 8;
-
- @Override
- public int[] getHashes(byte[] value) {
- byte[] hash = Hashing.sha256().hashBytes(value).asBytes();
- ByteBuffer buffer = ByteBuffer.wrap(hash);
- int[] hashes = new int[NUM_INDEXES];
- for (int i = 0; i < NUM_INDEXES; i++) {
- hashes[i] = buffer.getInt();
- }
- return hashes;
- }
-}
diff --git a/nearby/service/java/com/android/server/nearby/common/bluetooth/BluetoothConsts.java b/nearby/service/java/com/android/server/nearby/common/bluetooth/BluetoothConsts.java
deleted file mode 100644
index 3a02b18fb8f800a056dd9ddbb748b4bd8fa50f1f..0000000000000000000000000000000000000000
--- a/nearby/service/java/com/android/server/nearby/common/bluetooth/BluetoothConsts.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.nearby.common.bluetooth;
-
-import java.util.UUID;
-
-/**
- * Bluetooth constants.
- */
-public class BluetoothConsts {
-
- /**
- * Default MTU when value is unknown.
- */
- public static final int DEFAULT_MTU = 23;
-
- // The following random uuids are used to indicate that the device has dynamic services.
- /**
- * UUID of dynamic service.
- */
- public static final UUID SERVICE_DYNAMIC_SERVICE =
- UUID.fromString("00000100-0af3-11e5-a6c0-1697f925ec7b");
-
- /**
- * UUID of dynamic characteristic.
- */
- public static final UUID SERVICE_DYNAMIC_CHARACTERISTIC =
- UUID.fromString("00002A05-0af3-11e5-a6c0-1697f925ec7b");
-}
diff --git a/nearby/service/java/com/android/server/nearby/common/bluetooth/BluetoothException.java b/nearby/service/java/com/android/server/nearby/common/bluetooth/BluetoothException.java
deleted file mode 100644
index db2e1ccfe385ac725964d73da24636ebdcf77142..0000000000000000000000000000000000000000
--- a/nearby/service/java/com/android/server/nearby/common/bluetooth/BluetoothException.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.nearby.common.bluetooth;
-
-/**
- * {@link Exception} thrown during a Bluetooth operation.
- */
-public class BluetoothException extends Exception {
- /** Constructor. */
- public BluetoothException(String message) {
- super(message);
- }
-
- /** Constructor. */
- public BluetoothException(String message, Throwable throwable) {
- super(message, throwable);
- }
-}
diff --git a/nearby/service/java/com/android/server/nearby/common/bluetooth/BluetoothGattException.java b/nearby/service/java/com/android/server/nearby/common/bluetooth/BluetoothGattException.java
deleted file mode 100644
index 5ac4882fc93747cf64c5f7924a2b7b691b961431..0000000000000000000000000000000000000000
--- a/nearby/service/java/com/android/server/nearby/common/bluetooth/BluetoothGattException.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.nearby.common.bluetooth;
-
-/**
- * Exception for Bluetooth GATT operations.
- */
-public class BluetoothGattException extends BluetoothException {
- private final int mErrorCode;
-
- /** Constructor. */
- public BluetoothGattException(String message, int errorCode) {
- super(message);
- mErrorCode = errorCode;
- }
-
- /** Constructor. */
- public BluetoothGattException(String message, int errorCode, Throwable cause) {
- super(message, cause);
- mErrorCode = errorCode;
- }
-
- /** Returns Gatt error code. */
- public int getGattErrorCode() {
- return mErrorCode;
- }
-}
diff --git a/nearby/service/java/com/android/server/nearby/common/bluetooth/BluetoothTimeoutException.java b/nearby/service/java/com/android/server/nearby/common/bluetooth/BluetoothTimeoutException.java
deleted file mode 100644
index 30fd1887ec2f4a7c56c0067bf5d7ceeeab4b0c0a..0000000000000000000000000000000000000000
--- a/nearby/service/java/com/android/server/nearby/common/bluetooth/BluetoothTimeoutException.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.nearby.common.bluetooth;
-
-/**
- * {@link Exception} thrown during a Bluetooth operation when a timeout occurs.
- */
-public class BluetoothTimeoutException extends BluetoothException {
-
- /** Constructor. */
- public BluetoothTimeoutException(String message) {
- super(message);
- }
-
- /** Constructor. */
- public BluetoothTimeoutException(String message, Throwable throwable) {
- super(message, throwable);
- }
-}
diff --git a/nearby/service/java/com/android/server/nearby/common/bluetooth/ReservedUuids.java b/nearby/service/java/com/android/server/nearby/common/bluetooth/ReservedUuids.java
deleted file mode 100644
index 249011a827e6f9dfa5ea281e692aed519bb952a0..0000000000000000000000000000000000000000
--- a/nearby/service/java/com/android/server/nearby/common/bluetooth/ReservedUuids.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.nearby.common.bluetooth;
-
-import java.util.UUID;
-
-/**
- * Reserved UUIDS by BT SIG.
- *
- * See https://developer.bluetooth.org for more details.
- */
-public class ReservedUuids {
- /** UUIDs reserved for services. */
- public static class Services {
- /**
- * The Device Information Service exposes manufacturer and/or vendor info about a device.
- *
- * See reserved UUID org.bluetooth.service.device_information.
- */
- public static final UUID DEVICE_INFORMATION = fromShortUuid((short) 0x180A);
-
- /**
- * Generic attribute service.
- *
- * See reserved UUID org.bluetooth.service.generic_attribute.
- */
- public static final UUID GENERIC_ATTRIBUTE = fromShortUuid((short) 0x1801);
- }
-
- /** UUIDs reserved for characteristics. */
- public static class Characteristics {
- /**
- * The value of this characteristic is a UTF-8 string representing the firmware revision for
- * the firmware within the device.
- *
- * See reserved UUID org.bluetooth.characteristic.firmware_revision_string.
- */
- public static final UUID FIRMWARE_REVISION_STRING = fromShortUuid((short) 0x2A26);
-
- /**
- * Service change characteristic.
- *
- * See reserved UUID org.bluetooth.characteristic.gatt.service_changed.
- */
- public static final UUID SERVICE_CHANGE = fromShortUuid((short) 0x2A05);
- }
-
- /** UUIDs reserved for descriptors. */
- public static class Descriptors {
- /**
- * This descriptor shall be persistent across connections for bonded devices. The Client
- * Characteristic Configuration descriptor is unique for each client. A client may read and
- * write this descriptor to determine and set the configuration for that client.
- * Authentication and authorization may be required by the server to write this descriptor.
- * The default value for the Client Characteristic Configuration descriptor is 0x00. Upon
- * connection of non-binded clients, this descriptor is set to the default value.
- *
- * See reserved UUID org.bluetooth.descriptor.gatt.client_characteristic_configuration.
- */
- public static final UUID CLIENT_CHARACTERISTIC_CONFIGURATION =
- fromShortUuid((short) 0x2902);
- }
-
- /** The base 128-bit UUID representation of a 16-bit UUID */
- public static final UUID BASE_16_BIT_UUID =
- UUID.fromString("00000000-0000-1000-8000-00805F9B34FB");
-
- /** Converts from short UUId to UUID. */
- public static UUID fromShortUuid(short shortUuid) {
- return new UUID(((((long) shortUuid) << 32) & 0x0000FFFF00000000L)
- | ReservedUuids.BASE_16_BIT_UUID.getMostSignificantBits(),
- ReservedUuids.BASE_16_BIT_UUID.getLeastSignificantBits());
- }
-}
diff --git a/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/AccountKeyGenerator.java b/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/AccountKeyGenerator.java
deleted file mode 100644
index 28a9c33a4f822e0ddbc9515d289e1cfa7d4aecfd..0000000000000000000000000000000000000000
--- a/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/AccountKeyGenerator.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.nearby.common.bluetooth.fastpair;
-
-import static com.android.server.nearby.common.bluetooth.fastpair.AesEcbSingleBlockEncryption.generateKey;
-
-import com.android.server.nearby.common.bluetooth.fastpair.Constants.FastPairService.AccountKeyCharacteristic;
-
-import java.security.NoSuchAlgorithmException;
-
-/**
- * This is to generate account key with fast-pair style.
- */
-public final class AccountKeyGenerator {
-
- // Generate a key where the first byte is always defined as the type, 0x04. This maintains 15
- // bytes of entropy in the key while also allowing providers to verify that they have received
- // a properly formatted key and decrypted it correctly, minimizing the risk of replay attacks.
-
- /**
- * Creates account key.
- */
- public static byte[] createAccountKey() throws NoSuchAlgorithmException {
- byte[] accountKey = generateKey();
- accountKey[0] = AccountKeyCharacteristic.TYPE;
- return accountKey;
- }
-
- private AccountKeyGenerator() {
- }
-}
diff --git a/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/AdditionalDataEncoder.java b/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/AdditionalDataEncoder.java
deleted file mode 100644
index c9ccfd503501b36e0787b66f47a3d6779ad9624d..0000000000000000000000000000000000000000
--- a/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/AdditionalDataEncoder.java
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.nearby.common.bluetooth.fastpair;
-
-import static com.android.server.nearby.common.bluetooth.fastpair.AesCtrMultipleBlockEncryption.NONCE_SIZE;
-
-import static com.google.common.primitives.Bytes.concat;
-
-import java.security.GeneralSecurityException;
-import java.util.Arrays;
-
-/**
- * Utilities for encoding/decoding the additional data packet and verifying both the data integrity
- * and the authentication.
- *
- *
Additional Data packet is:
- *
- *
- *
AdditionalData_Packet[0 - 7]: the first 8-byte of HMAC.
- *
AdditionalData_Packet[8 - var]: the encrypted message by AES-CTR, with 8-byte nonce
- * appended to the front.
- *
- *
- * See https://developers.google.com/nearby/fast-pair/spec#AdditionalData.
- */
-public final class AdditionalDataEncoder {
-
- static final int EXTRACT_HMAC_SIZE = 8;
- static final int MAX_LENGTH_OF_DATA = 64;
-
- /**
- * Encodes the given data to additional data packet by the given secret.
- */
- static byte[] encodeAdditionalDataPacket(byte[] secret, byte[] additionalData)
- throws GeneralSecurityException {
- if (secret == null || secret.length != AesCtrMultipleBlockEncryption.KEY_LENGTH) {
- throw new GeneralSecurityException(
- "Incorrect secret for encoding additional data packet, secret.length = "
- + (secret == null ? "NULL" : secret.length));
- }
-
- if ((additionalData == null)
- || (additionalData.length == 0)
- || (additionalData.length > MAX_LENGTH_OF_DATA)) {
- throw new GeneralSecurityException(
- "Invalid data for encoding additional data packet, data = "
- + (additionalData == null ? "NULL" : additionalData.length));
- }
-
- byte[] encryptedData = AesCtrMultipleBlockEncryption.encrypt(secret, additionalData);
- byte[] extractedHmac =
- Arrays.copyOf(HmacSha256.build(secret, encryptedData), EXTRACT_HMAC_SIZE);
-
- return concat(extractedHmac, encryptedData);
- }
-
- /**
- * Decodes additional data packet by the given secret.
- *
- * @param secret AES-128 key used in the encryption to decrypt data
- * @param additionalDataPacket additional data packet which is encoded by the given secret
- * @return the data byte array decoded from the given packet
- * @throws GeneralSecurityException if the given key or additional data packet is invalid for
- * decoding
- */
- static byte[] decodeAdditionalDataPacket(byte[] secret, byte[] additionalDataPacket)
- throws GeneralSecurityException {
- if (secret == null || secret.length != AesCtrMultipleBlockEncryption.KEY_LENGTH) {
- throw new GeneralSecurityException(
- "Incorrect secret for decoding additional data packet, secret.length = "
- + (secret == null ? "NULL" : secret.length));
- }
- if (additionalDataPacket == null
- || additionalDataPacket.length <= EXTRACT_HMAC_SIZE
- || additionalDataPacket.length
- > (MAX_LENGTH_OF_DATA + EXTRACT_HMAC_SIZE + NONCE_SIZE)) {
- throw new GeneralSecurityException(
- "Additional data packet size is incorrect, additionalDataPacket.length is "
- + (additionalDataPacket == null ? "NULL"
- : additionalDataPacket.length));
- }
-
- if (!verifyHmac(secret, additionalDataPacket)) {
- throw new GeneralSecurityException(
- "Verify HMAC failed, could be incorrect key or packet.");
- }
- byte[] encryptedData =
- Arrays.copyOfRange(
- additionalDataPacket, EXTRACT_HMAC_SIZE, additionalDataPacket.length);
- return AesCtrMultipleBlockEncryption.decrypt(secret, encryptedData);
- }
-
- // Computes the HMAC of the given key and additional data, and compares the first 8-byte of the
- // HMAC result with the one from additional data packet.
- // Must call constant-time comparison to prevent a possible timing attack, e.g. time the same
- // MAC with all different first byte for a given ciphertext, the right one will take longer as
- // it will fail on the second byte's verification.
- private static boolean verifyHmac(byte[] key, byte[] additionalDataPacket)
- throws GeneralSecurityException {
- byte[] packetHmac =
- Arrays.copyOfRange(additionalDataPacket, /* from= */ 0, EXTRACT_HMAC_SIZE);
- byte[] encryptedData =
- Arrays.copyOfRange(
- additionalDataPacket, EXTRACT_HMAC_SIZE, additionalDataPacket.length);
- byte[] computedHmac = Arrays.copyOf(
- HmacSha256.build(key, encryptedData), EXTRACT_HMAC_SIZE);
-
- return HmacSha256.compareTwoHMACs(packetHmac, computedHmac);
- }
-
- private AdditionalDataEncoder() {
- }
-}
diff --git a/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/AesCtrMultipleBlockEncryption.java b/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/AesCtrMultipleBlockEncryption.java
deleted file mode 100644
index 50a818b722f07e08634f98db301d2ad099827846..0000000000000000000000000000000000000000
--- a/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/AesCtrMultipleBlockEncryption.java
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.nearby.common.bluetooth.fastpair;
-
-import static com.google.common.primitives.Bytes.concat;
-
-import androidx.annotation.VisibleForTesting;
-
-import java.security.GeneralSecurityException;
-import java.security.NoSuchAlgorithmException;
-import java.security.SecureRandom;
-import java.util.Arrays;
-
-/**
- * AES-CTR utilities used for encrypting and decrypting Fast Pair packets that contain multiple
- * blocks. Encrypts input data by:
- *
- *
- *
encryptedBlock[i] = clearBlock[i] ^ AES(counter), and
- *
concat(encryptedBlock[0], encryptedBlock[1],...) to create the encrypted result, where
- *
counter: the 16-byte input of AES. counter = iv + block_index.
- *
iv: extend 8-byte nonce to 16 bytes with zero padding. i.e. concat(0x0000000000000000,
- * nonce).
- *
nonce: the cryptographically random 8 bytes, must never be reused with the same key.
- *
- */
-final class AesCtrMultipleBlockEncryption {
-
- /** Length for AES-128 key. */
- static final int KEY_LENGTH = AesEcbSingleBlockEncryption.KEY_LENGTH;
-
- @VisibleForTesting
- static final int AES_BLOCK_LENGTH = AesEcbSingleBlockEncryption.AES_BLOCK_LENGTH;
-
- /** Length of the nonce, a byte array of cryptographically random bytes. */
- static final int NONCE_SIZE = 8;
-
- private static final int IV_SIZE = AES_BLOCK_LENGTH;
- private static final int MAX_NUMBER_OF_BLOCKS = 4;
-
- private AesCtrMultipleBlockEncryption() {}
-
- /** Generates a 16-byte AES key. */
- static byte[] generateKey() throws NoSuchAlgorithmException {
- return AesEcbSingleBlockEncryption.generateKey();
- }
-
- /**
- * Encrypts data using AES-CTR by the given secret.
- *
- * @param secret AES-128 key.
- * @param data the plaintext to be encrypted.
- * @return the encrypted data with the 8-byte nonce appended to the front.
- */
- static byte[] encrypt(byte[] secret, byte[] data) throws GeneralSecurityException {
- byte[] nonce = generateNonce();
- return concat(nonce, doAesCtr(secret, data, nonce));
- }
-
- /**
- * Decrypts data using AES-CTR by the given secret and nonce.
- *
- * @param secret AES-128 key.
- * @param data the first 8 bytes is the nonce, and the remaining is the encrypted data to be
- * decrypted.
- * @return the decrypted data.
- */
- static byte[] decrypt(byte[] secret, byte[] data) throws GeneralSecurityException {
- if (data == null || data.length <= NONCE_SIZE) {
- throw new GeneralSecurityException(
- "Incorrect data length "
- + (data == null ? "NULL" : data.length)
- + " to decrypt, the data should contain nonce.");
- }
- byte[] nonce = Arrays.copyOf(data, NONCE_SIZE);
- byte[] encryptedData = Arrays.copyOfRange(data, NONCE_SIZE, data.length);
- return doAesCtr(secret, encryptedData, nonce);
- }
-
- /**
- * Generates cryptographically random NONCE_SIZE bytes nonce. This nonce can be used only once.
- * Always call this function to generate a new nonce before a new encryption.
- */
- // Suppression for a warning for potentially insecure random numbers on Android 4.3 and older.
- // Fast Pair service is only for Android 6.0+ devices.
- static byte[] generateNonce() {
- SecureRandom random = new SecureRandom();
- byte[] nonce = new byte[NONCE_SIZE];
- random.nextBytes(nonce);
-
- return nonce;
- }
-
- // AES-CTR implementation.
- @VisibleForTesting
- static byte[] doAesCtr(byte[] secret, byte[] data, byte[] nonce)
- throws GeneralSecurityException {
- if (secret.length != KEY_LENGTH) {
- throw new IllegalArgumentException(
- "Incorrect key length for encryption, only supports 16-byte AES Key.");
- }
- if (nonce.length != NONCE_SIZE) {
- throw new IllegalArgumentException(
- "Incorrect nonce length for encryption, "
- + "Fast Pair naming scheme only supports 8-byte nonce.");
- }
-
- // Keeps the following operations on this byte[], returns it as the final AES-CTR result.
- byte[] aesCtrResult = new byte[data.length];
- System.arraycopy(data, /*srcPos=*/ 0, aesCtrResult, /*destPos=*/ 0, data.length);
-
- // Initializes counter as IV.
- byte[] counter = createIv(nonce);
- // The length of the given data is permitted to non-align block size.
- int numberOfBlocks =
- (data.length / AES_BLOCK_LENGTH) + ((data.length % AES_BLOCK_LENGTH == 0) ? 0 : 1);
-
- if (numberOfBlocks > MAX_NUMBER_OF_BLOCKS) {
- throw new IllegalArgumentException(
- "Incorrect data size, Fast Pair naming scheme only supports 4 blocks.");
- }
-
- for (int i = 0; i < numberOfBlocks; i++) {
- // Performs the operation: encryptedBlock[i] = clearBlock[i] ^ AES(counter).
- counter[0] = (byte) (i & 0xFF);
- byte[] aesOfCounter = doAesSingleBlock(secret, counter);
- int start = i * AES_BLOCK_LENGTH;
- // The size of the last block of data may not be 16 bytes. If not, still do xor to the
- // last byte of data.
- int end = Math.min(start + AES_BLOCK_LENGTH, data.length);
- for (int j = 0; start < end; j++, start++) {
- aesCtrResult[start] ^= aesOfCounter[j];
- }
- }
- return aesCtrResult;
- }
-
- private static byte[] doAesSingleBlock(byte[] secret, byte[] counter)
- throws GeneralSecurityException {
- return AesEcbSingleBlockEncryption.encrypt(secret, counter);
- }
-
- /** Extends 8-byte nonce to 16 bytes with zero padding to create IV. */
- private static byte[] createIv(byte[] nonce) {
- return concat(new byte[IV_SIZE - NONCE_SIZE], nonce);
- }
-}
diff --git a/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/AesEcbSingleBlockEncryption.java b/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/AesEcbSingleBlockEncryption.java
deleted file mode 100644
index 547931e651069c83a509b73ec8177e91400973bd..0000000000000000000000000000000000000000
--- a/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/AesEcbSingleBlockEncryption.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.nearby.common.bluetooth.fastpair;
-
-import android.annotation.SuppressLint;
-
-import java.security.GeneralSecurityException;
-import java.security.NoSuchAlgorithmException;
-
-import javax.crypto.Cipher;
-import javax.crypto.KeyGenerator;
-import javax.crypto.spec.SecretKeySpec;
-
-/**
- * Utilities used for encrypting and decrypting Fast Pair packets.
- */
-// SuppressLint for ""ecb encryption mode should not be used".
-// Reasons:
-// 1. FastPair data is guaranteed to be only 1 AES block in size, ECB is secure.
-// 2. In each case, the encrypted data is less than 16-bytes and is
-// padded up to 16-bytes using random data to fill the rest of the byte array,
-// so the plaintext will never be the same.
-@SuppressLint("GetInstance")
-public final class AesEcbSingleBlockEncryption {
-
- public static final int AES_BLOCK_LENGTH = 16;
- public static final int KEY_LENGTH = 16;
-
- private AesEcbSingleBlockEncryption() {
- }
-
- /**
- * Generates a 16-byte AES key.
- */
- public static byte[] generateKey() throws NoSuchAlgorithmException {
- KeyGenerator generator = KeyGenerator.getInstance("AES");
- generator.init(KEY_LENGTH * 8); // Ensure a 16-byte key is always used.
- return generator.generateKey().getEncoded();
- }
-
- /**
- * Encrypts data with the provided secret.
- */
- public static byte[] encrypt(byte[] secret, byte[] data) throws GeneralSecurityException {
- return doEncryption(Cipher.ENCRYPT_MODE, secret, data);
- }
-
- /**
- * Decrypts data with the provided secret.
- */
- public static byte[] decrypt(byte[] secret, byte[] data) throws GeneralSecurityException {
- return doEncryption(Cipher.DECRYPT_MODE, secret, data);
- }
-
- private static byte[] doEncryption(int mode, byte[] secret, byte[] data)
- throws GeneralSecurityException {
- if (data.length != AES_BLOCK_LENGTH) {
- throw new IllegalArgumentException("This encrypter only supports 16-byte inputs.");
- }
- Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");
- cipher.init(mode, new SecretKeySpec(secret, "AES"));
- return cipher.doFinal(data);
- }
-}
diff --git a/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/BluetoothAddress.java b/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/BluetoothAddress.java
deleted file mode 100644
index 9bb5a8601c3abff84ffb5bada12223a8988ec94b..0000000000000000000000000000000000000000
--- a/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/BluetoothAddress.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.nearby.common.bluetooth.fastpair;
-
-import static com.google.common.io.BaseEncoding.base16;
-
-import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.BluetoothDevice;
-import android.content.Context;
-import android.provider.Settings;
-
-import androidx.annotation.Nullable;
-import androidx.annotation.VisibleForTesting;
-
-import com.google.common.base.Ascii;
-import com.google.common.io.BaseEncoding;
-
-import java.util.Locale;
-
-/** Utils for dealing with Bluetooth addresses. */
-public final class BluetoothAddress {
-
- private static final BaseEncoding ENCODING = base16().upperCase().withSeparator(":", 2);
-
- @VisibleForTesting
- static final String SECURE_SETTINGS_KEY_BLUETOOTH_ADDRESS = "bluetooth_address";
-
- /**
- * @return The string format used by e.g. {@link android.bluetooth.BluetoothDevice}. Upper case.
- * Example: "AA:BB:CC:11:22:33"
- */
- public static String encode(byte[] address) {
- return ENCODING.encode(address);
- }
-
- /**
- * @param address The string format used by e.g. {@link android.bluetooth.BluetoothDevice}.
- * Case-insensitive. Example: "AA:BB:CC:11:22:33"
- */
- public static byte[] decode(String address) {
- return ENCODING.decode(address.toUpperCase(Locale.US));
- }
-
- /**
- * Get public bluetooth address.
- *
- * @param context a valid {@link Context} instance.
- */
- public static @Nullable byte[] getPublicAddress(Context context) {
- String publicAddress =
- Settings.Secure.getString(
- context.getContentResolver(), SECURE_SETTINGS_KEY_BLUETOOTH_ADDRESS);
- return publicAddress != null && BluetoothAdapter.checkBluetoothAddress(publicAddress)
- ? decode(publicAddress)
- : null;
- }
-
- /**
- * Hides partial information of Bluetooth address.
- * ex1: input is null, output should be empty string
- * ex2: input is String(AA:BB:CC), output should be AA:BB:CC
- * ex3: input is String(AA:BB:CC:DD:EE:FF), output should be XX:XX:XX:XX:EE:FF
- * ex4: input is String(Aa:Bb:Cc:Dd:Ee:Ff), output should be XX:XX:XX:XX:EE:FF
- * ex5: input is BluetoothDevice(AA:BB:CC:DD:EE:FF), output should be XX:XX:XX:XX:EE:FF
- */
- public static String maskBluetoothAddress(@Nullable Object address) {
- if (address == null) {
- return "";
- }
-
- if (address instanceof String) {
- String originalAddress = (String) address;
- String upperCasedAddress = Ascii.toUpperCase(originalAddress);
- if (!BluetoothAdapter.checkBluetoothAddress(upperCasedAddress)) {
- return originalAddress;
- }
- return convert(upperCasedAddress);
- } else if (address instanceof BluetoothDevice) {
- return convert(((BluetoothDevice) address).getAddress());
- }
-
- // For others, returns toString().
- return address.toString();
- }
-
- private static String convert(String address) {
- return "XX:XX:XX:XX:" + address.substring(12);
- }
-
- private BluetoothAddress() {}
-}
diff --git a/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/BluetoothAudioPairer.java b/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/BluetoothAudioPairer.java
deleted file mode 100644
index 07306c199f9bbcbae23c0cb0098bc913ccfeba6e..0000000000000000000000000000000000000000
--- a/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/BluetoothAudioPairer.java
+++ /dev/null
@@ -1,774 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.nearby.common.bluetooth.fastpair;
-
-import static android.bluetooth.BluetoothDevice.BOND_BONDED;
-import static android.bluetooth.BluetoothDevice.BOND_BONDING;
-import static android.bluetooth.BluetoothDevice.BOND_NONE;
-import static android.bluetooth.BluetoothDevice.ERROR;
-import static android.bluetooth.BluetoothProfile.A2DP;
-import static android.bluetooth.BluetoothProfile.HEADSET;
-import static android.content.pm.PackageManager.PERMISSION_GRANTED;
-
-import static com.android.server.nearby.common.bluetooth.fastpair.BluetoothAddress.maskBluetoothAddress;
-
-import static java.util.concurrent.Executors.newSingleThreadExecutor;
-
-import android.Manifest.permission;
-import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.BluetoothDevice;
-import android.bluetooth.BluetoothProfile;
-import android.content.Context;
-import android.content.Intent;
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.Parcelable;
-import android.os.SystemClock;
-import android.util.Log;
-
-import androidx.annotation.Nullable;
-import androidx.annotation.UiThread;
-import androidx.annotation.WorkerThread;
-import androidx.core.content.ContextCompat;
-
-import com.android.server.nearby.common.bluetooth.BluetoothException;
-import com.android.server.nearby.common.bluetooth.fastpair.Constants.FastPairService;
-import com.android.server.nearby.common.bluetooth.fastpair.Constants.FastPairService.PasskeyCharacteristic;
-import com.android.server.nearby.common.bluetooth.fastpair.Constants.Profile;
-import com.android.server.nearby.common.bluetooth.fastpair.TimingLogger.ScopedTiming;
-import com.android.server.nearby.common.bluetooth.gatt.BluetoothGattConnection;
-import com.android.server.nearby.common.bluetooth.gatt.BluetoothGattConnection.ChangeObserver;
-import com.android.server.nearby.intdefs.FastPairEventIntDefs.ConnectErrorCode;
-import com.android.server.nearby.intdefs.FastPairEventIntDefs.CreateBondErrorCode;
-import com.android.server.nearby.intdefs.NearbyEventIntDefs.EventCode;
-
-import com.google.common.base.Preconditions;
-import com.google.common.util.concurrent.SettableFuture;
-
-import java.security.GeneralSecurityException;
-import java.util.Arrays;
-import java.util.UUID;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-/**
- * Pairs to Bluetooth audio devices.
- */
-public class BluetoothAudioPairer {
-
- private static final String TAG = BluetoothAudioPairer.class.getSimpleName();
-
- /**
- * Hidden, see {@link BluetoothDevice}.
- */
- // TODO(b/202549655): remove Hidden usage.
- private static final String EXTRA_REASON = "android.bluetooth.device.extra.REASON";
-
- /**
- * Hidden, see {@link BluetoothDevice}.
- */
- // TODO(b/202549655): remove Hidden usage.
- private static final int PAIRING_VARIANT_CONSENT = 3;
-
- /**
- * Hidden, see {@link BluetoothDevice}.
- */
- // TODO(b/202549655): remove Hidden usage.
- public static final int PAIRING_VARIANT_DISPLAY_PASSKEY = 4;
-
- private static final int DISCOVERY_STATE_CHANGE_TIMEOUT_MS = 3000;
-
- private final Context mContext;
- private final Preferences mPreferences;
- private final EventLoggerWrapper mEventLogger;
- private final BluetoothDevice mDevice;
- @Nullable
- private final KeyBasedPairingInfo mKeyBasedPairingInfo;
- @Nullable
- private final PasskeyConfirmationHandler mPasskeyConfirmationHandler;
- private final TimingLogger mTimingLogger;
-
- private static boolean sTestMode = false;
-
- static void enableTestMode() {
- sTestMode = true;
- }
-
- static class KeyBasedPairingInfo {
-
- private final byte[] mSecret;
- private final GattConnectionManager mGattConnectionManager;
- private final boolean mProviderInitiatesBonding;
-
- /**
- * @param secret The secret negotiated during the initial BLE handshake for Key-based
- * Pairing. See {@link FastPairConnection#handshake}.
- * @param gattConnectionManager A manager that knows how to get and create Gatt connections
- * to the remote device.
- */
- KeyBasedPairingInfo(
- byte[] secret,
- GattConnectionManager gattConnectionManager,
- boolean providerInitiatesBonding) {
- this.mSecret = secret;
- this.mGattConnectionManager = gattConnectionManager;
- this.mProviderInitiatesBonding = providerInitiatesBonding;
- }
- }
-
- public BluetoothAudioPairer(
- Context context,
- BluetoothDevice device,
- Preferences preferences,
- EventLoggerWrapper eventLogger,
- @Nullable KeyBasedPairingInfo keyBasedPairingInfo,
- @Nullable PasskeyConfirmationHandler passkeyConfirmationHandler,
- TimingLogger timingLogger)
- throws PairingException {
- this.mContext = context;
- this.mDevice = device;
- this.mPreferences = preferences;
- this.mEventLogger = eventLogger;
- this.mKeyBasedPairingInfo = keyBasedPairingInfo;
- this.mPasskeyConfirmationHandler = passkeyConfirmationHandler;
- this.mTimingLogger = timingLogger;
-
- // TODO(b/203455314): follow up with the following comments.
- // The OS should give the user some UI to choose if they want to allow access, but there
- // seems to be a bug where if we don't reject access, it's auto-granted in some cases
- // (Plantronics headset gets contacts access when pairing with my Taimen via Bluetooth
- // Settings, without me seeing any UI about it). b/64066631
- //
- // If that OS bug doesn't get fixed, we can flip these flags to force-reject the
- // permissions.
- if (preferences.getRejectPhonebookAccess() && (sTestMode ? false :
- !device.setPhonebookAccessPermission(BluetoothDevice.ACCESS_REJECTED))) {
- throw new PairingException("Failed to deny contacts (phonebook) access.");
- }
- if (preferences.getRejectMessageAccess()
- && (sTestMode ? false :
- !device.setMessageAccessPermission(BluetoothDevice.ACCESS_REJECTED))) {
- throw new PairingException("Failed to deny message access.");
- }
- if (preferences.getRejectSimAccess()
- && (sTestMode ? false :
- !device.setSimAccessPermission(BluetoothDevice.ACCESS_REJECTED))) {
- throw new PairingException("Failed to deny SIM access.");
- }
- }
-
- boolean isPaired() {
- return (sTestMode ? false : mDevice.getBondState() == BOND_BONDED);
- }
-
- /**
- * Unpairs from the device. Throws an exception if any error occurs.
- */
- @WorkerThread
- void unpair()
- throws InterruptedException, ExecutionException, TimeoutException, PairingException {
- int bondState = sTestMode ? BOND_NONE : mDevice.getBondState();
- try (UnbondedReceiver unbondedReceiver = new UnbondedReceiver();
- ScopedTiming scopedTiming = new ScopedTiming(mTimingLogger,
- "Unpair for state: " + bondState)) {
- // We'll only get a state change broadcast if we're actually unbonding (method returns
- // true).
- if (bondState == BluetoothDevice.BOND_BONDED) {
- mEventLogger.setCurrentEvent(EventCode.REMOVE_BOND);
- Log.i(TAG, "removeBond with " + maskBluetoothAddress(mDevice));
- mDevice.removeBond();
- unbondedReceiver.await(
- mPreferences.getRemoveBondTimeoutSeconds(), TimeUnit.SECONDS);
- } else if (bondState == BluetoothDevice.BOND_BONDING) {
- mEventLogger.setCurrentEvent(EventCode.CANCEL_BOND);
- Log.i(TAG, "cancelBondProcess with " + maskBluetoothAddress(mDevice));
- mDevice.cancelBondProcess();
- unbondedReceiver.await(
- mPreferences.getRemoveBondTimeoutSeconds(), TimeUnit.SECONDS);
- } else {
- // The OS may have beaten us in a race, unbonding before we called the method. So if
- // we're (somehow) in the desired state then we're happy, if not then bail.
- if (bondState != BluetoothDevice.BOND_NONE) {
- throw new PairingException("returned false, state=%s", bondState);
- }
- }
- }
-
- // This seems to improve the probability that createBond will succeed after removeBond.
- SystemClock.sleep(mPreferences.getRemoveBondSleepMillis());
- mEventLogger.logCurrentEventSucceeded();
- }
-
- /**
- * Pairs with the device. Throws an exception if any error occurs.
- */
- @WorkerThread
- void pair()
- throws InterruptedException, ExecutionException, TimeoutException, PairingException {
- // Unpair first, because if we have a bond, but the other device has forgotten its bond,
- // it can send us a pairing request that we're not ready for (which can pop up a dialog).
- // Or, if we're in the middle of a (too-long) bonding attempt, we want to cancel.
- unpair();
-
- mEventLogger.setCurrentEvent(EventCode.CREATE_BOND);
- try (BondedReceiver bondedReceiver = new BondedReceiver();
- ScopedTiming scopedTiming = new ScopedTiming(mTimingLogger, "Create bond")) {
- // If the provider's initiating the bond, we do nothing but wait for broadcasts.
- if (mKeyBasedPairingInfo == null || !mKeyBasedPairingInfo.mProviderInitiatesBonding) {
- if (!sTestMode) {
- Log.i(TAG, "createBond with " + maskBluetoothAddress(mDevice) + ", type="
- + mDevice.getType());
- if (mPreferences.getSpecifyCreateBondTransportType()) {
- mDevice.createBond(mPreferences.getCreateBondTransportType());
- } else {
- mDevice.createBond();
- }
- }
- }
- try {
- bondedReceiver.await(mPreferences.getCreateBondTimeoutSeconds(), TimeUnit.SECONDS);
- } catch (TimeoutException e) {
- Log.w(TAG, "bondedReceiver time out after " + mPreferences
- .getCreateBondTimeoutSeconds() + " seconds");
- if (mPreferences.getIgnoreUuidTimeoutAfterBonded() && isPaired()) {
- Log.w(TAG, "Created bond but never received UUIDs, attempting to continue.");
- } else {
- // Rethrow e to cause the pairing to fail and be retried if necessary.
- throw e;
- }
- }
- }
- mEventLogger.logCurrentEventSucceeded();
- }
-
- /**
- * Connects to the given profile. Throws an exception if any error occurs.
- *
- *
If remote device clears the link key, the BOND_BONDED state would transit to BOND_BONDING
- * (and go through the pairing process again) when directly connecting the profile. By enabling
- * enablePairingBehavior, we provide both pairing and connecting behaviors at the same time. See
- * b/145699390 for more details.
- */
- // Suppression for possible null from ImmutableMap#get. See go/lsc-get-nullable
- @SuppressWarnings("nullness:argument")
- @WorkerThread
- public void connect(short profileUuid, boolean enablePairingBehavior)
- throws InterruptedException, ReflectionException, TimeoutException, ExecutionException,
- ConnectException {
- if (!mPreferences.isSupportedProfile(profileUuid)) {
- throw new ConnectException(
- ConnectErrorCode.UNSUPPORTED_PROFILE, "Unsupported profile=%s", profileUuid);
- }
- Profile profile = Constants.PROFILES.get(profileUuid);
- Log.i(TAG,
- "Connecting to profile=" + profile + " on device=" + maskBluetoothAddress(mDevice));
- try (BondedReceiver bondedReceiver = enablePairingBehavior ? new BondedReceiver() : null;
- ScopedTiming scopedTiming = new ScopedTiming(mTimingLogger,
- "Connect: " + profile)) {
- connectByProfileProxy(profile);
- }
- }
-
- private void connectByProfileProxy(Profile profile)
- throws ReflectionException, InterruptedException, ExecutionException, TimeoutException,
- ConnectException {
- try (BluetoothProfileWrapper autoClosingProxy = new BluetoothProfileWrapper(profile);
- ConnectedReceiver connectedReceiver = new ConnectedReceiver(profile)) {
- BluetoothProfile proxy = autoClosingProxy.mProxy;
-
- // Try to connect via reflection
- Log.v(TAG, "Connect to proxy=" + proxy);
-
- if (!sTestMode) {
- if (!(Boolean) Reflect.on(proxy).withMethod("connect", BluetoothDevice.class)
- .get(mDevice)) {
- // If we're already connecting, connect() may return false. :/
- Log.w(TAG, "connect returned false, expected if connecting, state="
- + proxy.getConnectionState(mDevice));
- }
- }
-
- // If we're already connected, the OS may not send the connection state broadcast, so
- // return immediately for that case.
- if (!sTestMode) {
- if (proxy.getConnectionState(mDevice) == BluetoothProfile.STATE_CONNECTED) {
- Log.v(TAG, "connectByProfileProxy: already connected to device="
- + maskBluetoothAddress(mDevice));
- return;
- }
- }
-
- try (ScopedTiming scopedTiming = new ScopedTiming(mTimingLogger, "Wait connection")) {
- // Wait for connecting to succeed or fail (via event or timeout).
- connectedReceiver
- .await(mPreferences.getCreateBondTimeoutSeconds(), TimeUnit.SECONDS);
- }
- }
- }
-
- private class BluetoothProfileWrapper implements AutoCloseable {
-
- // incompatible types in assignment.
- @SuppressWarnings("nullness:assignment")
- private final BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
-
- private final Profile mProfile;
- private final BluetoothProfile mProxy;
-
- /**
- * Blocks until we get the proxy. Throws on error.
- */
- private BluetoothProfileWrapper(Profile profile)
- throws InterruptedException, ExecutionException, TimeoutException,
- ConnectException {
- this.mProfile = profile;
- mProxy = getProfileProxy(profile);
- }
-
- @Override
- public void close() {
- try (ScopedTiming scopedTiming =
- new ScopedTiming(mTimingLogger, "Close profile: " + mProfile)) {
- if (!sTestMode) {
- mBluetoothAdapter.closeProfileProxy(mProfile.type, mProxy);
- }
- }
- }
-
- private BluetoothProfile getProfileProxy(BluetoothProfileWrapper this, Profile profile)
- throws InterruptedException, ExecutionException, TimeoutException,
- ConnectException {
- if (profile.type != A2DP && profile.type != HEADSET) {
- throw new IllegalArgumentException("Unsupported profile type=" + profile.type);
- }
-
- SettableFuture proxyFuture = SettableFuture.create();
- BluetoothProfile.ServiceListener listener =
- new BluetoothProfile.ServiceListener() {
- @UiThread
- @Override
- public void onServiceConnected(int profileType, BluetoothProfile proxy) {
- proxyFuture.set(proxy);
- }
-
- @Override
- public void onServiceDisconnected(int profileType) {
- Log.v(TAG, "proxy disconnected for profile=" + profile);
- }
- };
-
- if (!mBluetoothAdapter.getProfileProxy(mContext, listener, profile.type)) {
- throw new ConnectException(
- ConnectErrorCode.GET_PROFILE_PROXY_FAILED,
- "getProfileProxy failed immediately");
- }
-
- return proxyFuture.get(mPreferences.getProxyTimeoutSeconds(), TimeUnit.SECONDS);
- }
- }
-
- private class UnbondedReceiver extends DeviceIntentReceiver {
-
- private UnbondedReceiver() {
- super(mContext, mPreferences, mDevice, BluetoothDevice.ACTION_BOND_STATE_CHANGED);
- }
-
- @Override
- protected void onReceiveDeviceIntent(Intent intent) throws Exception {
- if (mDevice.getBondState() == BOND_NONE) {
- try (ScopedTiming scopedTiming = new ScopedTiming(mTimingLogger,
- "Close UnbondedReceiver")) {
- close();
- }
- }
- }
- }
-
- /**
- * Receiver that closes after bonding has completed.
- */
- class BondedReceiver extends DeviceIntentReceiver {
-
- private boolean mReceivedUuids = false;
- private boolean mReceivedPasskey = false;
-
- private BondedReceiver() {
- super(
- mContext,
- mPreferences,
- mDevice,
- BluetoothDevice.ACTION_PAIRING_REQUEST,
- BluetoothDevice.ACTION_BOND_STATE_CHANGED,
- BluetoothDevice.ACTION_UUID);
- }
-
- // switching on a possibly-null value (intent.getAction())
- // incompatible types in argument.
- @SuppressWarnings({"nullness:switching.nullable", "nullness:argument"})
- @Override
- protected void onReceiveDeviceIntent(Intent intent)
- throws PairingException, InterruptedException, ExecutionException, TimeoutException,
- BluetoothException, GeneralSecurityException {
- switch (intent.getAction()) {
- case BluetoothDevice.ACTION_PAIRING_REQUEST:
- int variant = intent.getIntExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT, ERROR);
- int passkey = intent.getIntExtra(BluetoothDevice.EXTRA_PAIRING_KEY, ERROR);
- handlePairingRequest(variant, passkey);
- break;
- case BluetoothDevice.ACTION_BOND_STATE_CHANGED:
- // Use the state in the intent, not device.getBondState(), to avoid a race where
- // we log the wrong failure reason during a rapid transition.
- int bondState = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, ERROR);
- int reason = intent.getIntExtra(EXTRA_REASON, ERROR);
- handleBondStateChanged(bondState, reason);
- break;
- case BluetoothDevice.ACTION_UUID:
- // According to eisenbach@ and pavlin@, there's always a UUID broadcast when
- // pairing (it can happen either before or after the transition to BONDED).
- if (mPreferences.getWaitForUuidsAfterBonding()) {
- Parcelable[] uuids = intent
- .getParcelableArrayExtra(BluetoothDevice.EXTRA_UUID);
- handleUuids(uuids);
- }
- break;
- default:
- break;
- }
- }
-
- private void handlePairingRequest(int variant, int passkey) {
- Log.i(TAG, "Pairing request, variant=" + variant + ", passkey=" + (passkey == ERROR
- ? "(none)" : String.valueOf(passkey)));
- if (mPreferences.getMoreEventLogForQuality()) {
- mEventLogger.setCurrentEvent(EventCode.HANDLE_PAIRING_REQUEST);
- }
-
- if (mPreferences.getSupportHidDevice() && variant == PAIRING_VARIANT_DISPLAY_PASSKEY) {
- mReceivedPasskey = true;
- extendAwaitSecond(
- mPreferences.getHidCreateBondTimeoutSeconds()
- - mPreferences.getCreateBondTimeoutSeconds());
- triggerDiscoverStateChange();
- if (mPreferences.getMoreEventLogForQuality()) {
- mEventLogger.logCurrentEventSucceeded();
- }
- return;
-
- } else {
- // Prevent Bluetooth Settings from getting the pairing request and showing its own
- // UI.
- abortBroadcast();
-
- if (variant == PAIRING_VARIANT_CONSENT
- && mKeyBasedPairingInfo == null // Fast Pair 1.0 device
- && mPreferences.getAcceptConsentForFastPairOne()) {
- // Previously, if Bluetooth decided to use the Just Works variant (e.g. Fast
- // Pair 1.0), we don't get a pairing request broadcast at all.
- // However, after CVE-2019-2225, Bluetooth will decide to ask consent from
- // users. Details:
- // https://source.android.com/security/bulletin/2019-12-01#system
- // Since we've certified the Fast Pair 1.0 devices, and user taps to pair it
- // (with the device's image), we could help user to accept the consent.
- if (!sTestMode) {
- mDevice.setPairingConfirmation(true);
- }
- if (mPreferences.getMoreEventLogForQuality()) {
- mEventLogger.logCurrentEventSucceeded();
- }
- return;
- } else if (variant != BluetoothDevice.PAIRING_VARIANT_PASSKEY_CONFIRMATION) {
- if (!sTestMode) {
- mDevice.setPairingConfirmation(false);
- }
- if (mPreferences.getMoreEventLogForQuality()) {
- mEventLogger.logCurrentEventFailed(
- new CreateBondException(
- CreateBondErrorCode.INCORRECT_VARIANT, 0,
- "Incorrect variant for FastPair"));
- }
- return;
- }
- mReceivedPasskey = true;
-
- if (mKeyBasedPairingInfo == null) {
- if (mPreferences.getAcceptPasskey()) {
- // Must be the simulator using FP 1.0 (no Key-based Pairing). Real
- // headphones using FP 1.0 use Just Works instead (and maybe we should
- // disable this flag for them).
- if (!sTestMode) {
- mDevice.setPairingConfirmation(true);
- }
- }
- if (mPreferences.getMoreEventLogForQuality()) {
- if (!sTestMode) {
- mEventLogger.logCurrentEventSucceeded();
- }
- }
- return;
- }
- }
-
- if (mPreferences.getMoreEventLogForQuality()) {
- mEventLogger.logCurrentEventSucceeded();
- }
-
- newSingleThreadExecutor()
- .execute(
- () -> {
- try (ScopedTiming scopedTiming1 =
- new ScopedTiming(mTimingLogger, "Exchange passkey")) {
- mEventLogger.setCurrentEvent(EventCode.PASSKEY_EXCHANGE);
-
- // We already check above, but the static analyzer's not
- // convinced without this.
- Preconditions.checkNotNull(mKeyBasedPairingInfo);
- BluetoothGattConnection connection =
- mKeyBasedPairingInfo.mGattConnectionManager
- .getConnection();
- UUID characteristicUuid =
- PasskeyCharacteristic.getId(connection);
- ChangeObserver remotePasskeyObserver =
- connection.enableNotification(FastPairService.ID,
- characteristicUuid);
- Log.i(TAG, "Sending local passkey.");
- byte[] encryptedData;
- try (ScopedTiming scopedTiming2 =
- new ScopedTiming(mTimingLogger, "Encrypt passkey")) {
- encryptedData =
- PasskeyCharacteristic.encrypt(
- PasskeyCharacteristic.Type.SEEKER,
- mKeyBasedPairingInfo.mSecret, passkey);
- }
- try (ScopedTiming scopedTiming3 =
- new ScopedTiming(mTimingLogger,
- "Send passkey to remote")) {
- connection.writeCharacteristic(
- FastPairService.ID, characteristicUuid,
- encryptedData);
- }
- Log.i(TAG, "Waiting for remote passkey.");
- byte[] encryptedRemotePasskey;
- try (ScopedTiming scopedTiming4 =
- new ScopedTiming(mTimingLogger,
- "Wait for remote passkey")) {
- encryptedRemotePasskey =
- remotePasskeyObserver.waitForUpdate(
- TimeUnit.SECONDS.toMillis(mPreferences
- .getGattOperationTimeoutSeconds()));
- }
- int remotePasskey;
- try (ScopedTiming scopedTiming5 =
- new ScopedTiming(mTimingLogger, "Decrypt passkey")) {
- remotePasskey =
- PasskeyCharacteristic.decrypt(
- PasskeyCharacteristic.Type.PROVIDER,
- mKeyBasedPairingInfo.mSecret,
- encryptedRemotePasskey);
- }
-
- // We log success if we made it through with no exceptions.
- // If the passkey was wrong, pairing will fail and we'll log
- // BOND_BROKEN with reason = AUTH_FAILED.
- mEventLogger.logCurrentEventSucceeded();
-
- boolean isPasskeyCorrect = passkey == remotePasskey;
- if (isPasskeyCorrect) {
- Log.i(TAG, "Passkey correct.");
- } else {
- Log.e(TAG, "Passkey incorrect, local= " + passkey
- + ", remote=" + remotePasskey);
- }
-
- // Don't estimate the {@code ScopedTiming} because the
- // passkey confirmation is done by UI.
- if (isPasskeyCorrect
- && mPreferences.getHandlePasskeyConfirmationByUi()
- && mPasskeyConfirmationHandler != null) {
- Log.i(TAG, "Callback the passkey to UI for confirmation.");
- mPasskeyConfirmationHandler
- .onPasskeyConfirmation(mDevice, passkey);
- } else {
- try (ScopedTiming scopedTiming6 =
- new ScopedTiming(
- mTimingLogger, "Confirm the pairing: "
- + isPasskeyCorrect)) {
- mDevice.setPairingConfirmation(isPasskeyCorrect);
- }
- }
- } catch (BluetoothException
- | GeneralSecurityException
- | InterruptedException
- | ExecutionException
- | TimeoutException e) {
- mEventLogger.logCurrentEventFailed(e);
- closeWithError(e);
- }
- });
- }
-
- /**
- * Workaround to let Settings popup a pairing dialog instead of notification. When pairing
- * request intent passed to Settings, it'll check several conditions to decide that it
- * should show a dialog or a notification. One of those conditions is to check if the device
- * is in discovery mode recently, which can be fulfilled by calling {@link
- * BluetoothAdapter#startDiscovery()}. This method aims to fulfill the condition, and block
- * the pairing broadcast for at most
- * {@link BluetoothAudioPairer#DISCOVERY_STATE_CHANGE_TIMEOUT_MS}
- * to make sure that we fulfill the condition first and successful.
- */
- // dereference of possibly-null reference bluetoothAdapter
- @SuppressWarnings("nullness:dereference.of.nullable")
- private void triggerDiscoverStateChange() {
- BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
-
- if (bluetoothAdapter.isDiscovering()) {
- return;
- }
-
- HandlerThread backgroundThread = new HandlerThread("TriggerDiscoverStateChangeThread");
- backgroundThread.start();
-
- AtomicBoolean result = new AtomicBoolean(false);
- SimpleBroadcastReceiver receiver =
- new SimpleBroadcastReceiver(
- mContext,
- mPreferences,
- new Handler(backgroundThread.getLooper()),
- BluetoothAdapter.ACTION_DISCOVERY_STARTED,
- BluetoothAdapter.ACTION_DISCOVERY_FINISHED) {
-
- @Override
- protected void onReceive(Intent intent) throws Exception {
- result.set(true);
- close();
- }
- };
-
- Log.i(TAG, "triggerDiscoverStateChange call startDiscovery.");
- // Uses startDiscovery to trigger Settings show pairing dialog instead of notification.
- if (!sTestMode) {
- bluetoothAdapter.startDiscovery();
- bluetoothAdapter.cancelDiscovery();
- }
- try {
- receiver.await(DISCOVERY_STATE_CHANGE_TIMEOUT_MS, TimeUnit.MILLISECONDS);
- } catch (InterruptedException | ExecutionException | TimeoutException e) {
- Log.w(TAG, "triggerDiscoverStateChange failed!");
- }
-
- backgroundThread.quitSafely();
- try {
- backgroundThread.join();
- } catch (InterruptedException e) {
- Log.i(TAG, "triggerDiscoverStateChange backgroundThread.join meet exception!", e);
- }
-
- if (result.get()) {
- Log.i(TAG, "triggerDiscoverStateChange successful.");
- }
- }
-
- private void handleBondStateChanged(int bondState, int reason)
- throws PairingException, InterruptedException, ExecutionException,
- TimeoutException {
- Log.i(TAG, "Bond state changed to " + bondState + ", reason=" + reason);
- switch (bondState) {
- case BOND_BONDED:
- if (mKeyBasedPairingInfo != null && !mReceivedPasskey) {
- // The device bonded with Just Works, although we did the Key-based Pairing
- // GATT handshake and agreed on a pairing secret. It might be a Person In
- // The Middle Attack!
- try (ScopedTiming scopedTiming =
- new ScopedTiming(mTimingLogger,
- "Close BondedReceiver: POSSIBLE_MITM")) {
- closeWithError(
- new CreateBondException(
- CreateBondErrorCode.POSSIBLE_MITM,
- reason,
- "Unexpectedly bonded without a passkey. It might be a "
- + "Person In The Middle Attack! Unbonding!"));
- }
- unpair();
- } else if (!mPreferences.getWaitForUuidsAfterBonding()
- || (mPreferences.getReceiveUuidsAndBondedEventBeforeClose()
- && mReceivedUuids)) {
- try (ScopedTiming scopedTiming =
- new ScopedTiming(mTimingLogger, "Close BondedReceiver")) {
- close();
- }
- }
- break;
- case BOND_NONE:
- throw new CreateBondException(
- CreateBondErrorCode.BOND_BROKEN, reason, "Bond broken, reason=%d",
- reason);
- case BOND_BONDING:
- default:
- break;
- }
- }
-
- private void handleUuids(Parcelable[] uuids) {
- Log.i(TAG, "Got UUIDs for " + maskBluetoothAddress(mDevice) + ": "
- + Arrays.toString(uuids));
- mReceivedUuids = true;
- if (!mPreferences.getReceiveUuidsAndBondedEventBeforeClose() || isPaired()) {
- try (ScopedTiming scopedTiming = new ScopedTiming(mTimingLogger,
- "Close BondedReceiver")) {
- close();
- }
- }
- }
- }
-
- private class ConnectedReceiver extends DeviceIntentReceiver {
-
- private ConnectedReceiver(Profile profile) throws ConnectException {
- super(mContext, mPreferences, mDevice, profile.connectionStateAction);
- }
-
- @Override
- public void onReceiveDeviceIntent(Intent intent) throws PairingException {
- int state = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, ERROR);
- Log.i(TAG, "Connection state changed to " + state);
- switch (state) {
- case BluetoothAdapter.STATE_CONNECTED:
- try (ScopedTiming scopedTiming =
- new ScopedTiming(mTimingLogger, "Close ConnectedReceiver")) {
- close();
- }
- break;
- case BluetoothAdapter.STATE_DISCONNECTED:
- throw new ConnectException(ConnectErrorCode.DISCONNECTED, "Disconnected");
- case BluetoothAdapter.STATE_CONNECTING:
- case BluetoothAdapter.STATE_DISCONNECTING:
- default:
- break;
- }
- }
- }
-
- private boolean hasPermission(String permission) {
- return ContextCompat.checkSelfPermission(mContext, permission) == PERMISSION_GRANTED;
- }
-
- public BluetoothDevice getDevice() {
- return mDevice;
- }
-}
diff --git a/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/BluetoothClassicPairer.java b/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/BluetoothClassicPairer.java
deleted file mode 100644
index 6c467d3cf04f7ef3b9d5ee3e0b3948d12c5c60e0..0000000000000000000000000000000000000000
--- a/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/BluetoothClassicPairer.java
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.nearby.common.bluetooth.fastpair;
-
-import static android.bluetooth.BluetoothDevice.BOND_BONDED;
-import static android.bluetooth.BluetoothDevice.BOND_BONDING;
-import static android.bluetooth.BluetoothDevice.BOND_NONE;
-import static android.bluetooth.BluetoothDevice.ERROR;
-import static android.bluetooth.BluetoothDevice.EXTRA_DEVICE;
-
-import static com.android.server.nearby.common.bluetooth.fastpair.BluetoothAddress.maskBluetoothAddress;
-
-import static java.util.concurrent.TimeUnit.SECONDS;
-
-import android.annotation.SuppressLint;
-import android.bluetooth.BluetoothDevice;
-import android.content.Context;
-import android.content.Intent;
-import android.util.Log;
-
-import androidx.annotation.WorkerThread;
-
-import com.google.common.base.Strings;
-
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeoutException;
-
-/**
- * Pairs to Bluetooth classic devices with passkey confirmation.
- */
-// TODO(b/202524672): Add class unit test.
-public class BluetoothClassicPairer {
-
- private static final String TAG = BluetoothClassicPairer.class.getSimpleName();
- /**
- * Hidden, see {@link BluetoothDevice}.
- */
- private static final String EXTRA_REASON = "android.bluetooth.device.extra.REASON";
-
- private final Context mContext;
- private final BluetoothDevice mDevice;
- private final Preferences mPreferences;
- private final PasskeyConfirmationHandler mPasskeyConfirmationHandler;
-
- public BluetoothClassicPairer(
- Context context,
- BluetoothDevice device,
- Preferences preferences,
- PasskeyConfirmationHandler passkeyConfirmationHandler) {
- this.mContext = context;
- this.mDevice = device;
- this.mPreferences = preferences;
- this.mPasskeyConfirmationHandler = passkeyConfirmationHandler;
- }
-
- /**
- * Pairs with the device. Throws a {@link PairingException} if any error occurs.
- */
- @WorkerThread
- public void pair() throws PairingException {
- Log.i(TAG, "BluetoothClassicPairer, createBond with " + maskBluetoothAddress(mDevice)
- + ", type=" + mDevice.getType());
- try (BondedReceiver bondedReceiver = new BondedReceiver()) {
- if (mDevice.createBond()) {
- bondedReceiver.await(mPreferences.getCreateBondTimeoutSeconds(), SECONDS);
- } else {
- throw new PairingException(
- "BluetoothClassicPairer, createBond got immediate error");
- }
- } catch (TimeoutException | InterruptedException | ExecutionException e) {
- throw new PairingException("BluetoothClassicPairer, createBond failed", e);
- }
- }
-
- protected boolean isPaired() {
- return mDevice.getBondState() == BOND_BONDED;
- }
-
- /**
- * Receiver that closes after bonding has completed.
- */
- private class BondedReceiver extends DeviceIntentReceiver {
-
- private BondedReceiver() {
- super(
- mContext,
- mPreferences,
- mDevice,
- BluetoothDevice.ACTION_PAIRING_REQUEST,
- BluetoothDevice.ACTION_BOND_STATE_CHANGED);
- }
-
- /**
- * Called with ACTION_PAIRING_REQUEST and ACTION_BOND_STATE_CHANGED about the interesting
- * device (see {@link DeviceIntentReceiver}).
- *
- *
The ACTION_PAIRING_REQUEST intent provides the passkey which will be sent to the
- * {@link PasskeyConfirmationHandler} for showing the UI, and the ACTION_BOND_STATE_CHANGED
- * will provide the result of the bonding.
- */
- @Override
- protected void onReceiveDeviceIntent(Intent intent) {
- String intentAction = intent.getAction();
- BluetoothDevice remoteDevice = intent.getParcelableExtra(EXTRA_DEVICE);
- if (Strings.isNullOrEmpty(intentAction)
- || remoteDevice == null
- || !remoteDevice.getAddress().equals(mDevice.getAddress())) {
- Log.w(TAG,
- "BluetoothClassicPairer, receives " + intentAction
- + " from unexpected device " + maskBluetoothAddress(remoteDevice));
- return;
- }
- switch (intentAction) {
- case BluetoothDevice.ACTION_PAIRING_REQUEST:
- handlePairingRequest(
- remoteDevice,
- intent.getIntExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT, ERROR),
- intent.getIntExtra(BluetoothDevice.EXTRA_PAIRING_KEY, ERROR));
- break;
- case BluetoothDevice.ACTION_BOND_STATE_CHANGED:
- handleBondStateChanged(
- intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, ERROR),
- intent.getIntExtra(EXTRA_REASON, ERROR));
- break;
- default:
- break;
- }
- }
-
- private void handlePairingRequest(BluetoothDevice device, int variant, int passkey) {
- Log.i(TAG,
- "BluetoothClassicPairer, pairing request, " + device + ", " + variant + ", "
- + passkey);
- // Prevent Bluetooth Settings from getting the pairing request and showing its own UI.
- abortBroadcast();
- mPasskeyConfirmationHandler.onPasskeyConfirmation(device, passkey);
- }
-
- private void handleBondStateChanged(int bondState, int reason) {
- Log.i(TAG,
- "BluetoothClassicPairer, bond state changed to " + bondState + ", reason="
- + reason);
- switch (bondState) {
- case BOND_BONDING:
- // Don't close!
- return;
- case BOND_BONDED:
- close();
- return;
- case BOND_NONE:
- default:
- closeWithError(
- new PairingException(
- "BluetoothClassicPairer, createBond failed, reason:" + reason));
- }
- }
- }
-
- // Applies UsesPermission annotation will create circular dependency.
- @SuppressLint("MissingPermission")
- static void setPairingConfirmation(BluetoothDevice device, boolean confirm) {
- Log.i(TAG, "BluetoothClassicPairer: setPairingConfirmation " + maskBluetoothAddress(device)
- + ", confirm: " + confirm);
- device.setPairingConfirmation(confirm);
- }
-}
diff --git a/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/BluetoothUuids.java b/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/BluetoothUuids.java
deleted file mode 100644
index c5475a69ed09ce212cbd8ddbfe89e5bb45b84552..0000000000000000000000000000000000000000
--- a/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/BluetoothUuids.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.nearby.common.bluetooth.fastpair;
-
-import java.util.UUID;
-
-/**
- * Utilities for dealing with UUIDs assigned by the Bluetooth SIG. Has a lot in common with
- * com.android.BluetoothUuid, but that class is hidden.
- */
-public class BluetoothUuids {
-
- /**
- * The Base UUID is used for calculating 128-bit UUIDs from "short UUIDs" (16- and 32-bit).
- *
- * @see {https://www.bluetooth.com/specifications/assigned-numbers/service-discovery}
- */
- private static final UUID BASE_UUID = UUID.fromString("00000000-0000-1000-8000-00805F9B34FB");
-
- /**
- * Fast Pair custom GATT characteristics 128-bit UUIDs base.
- *
- *
Notes: The 16-bit value locates at the 3rd and 4th bytes.
- *
- * @see {go/fastpair-128bit-gatt}
- */
- private static final UUID FAST_PAIR_BASE_UUID =
- UUID.fromString("FE2C0000-8366-4814-8EB0-01DE32100BEA");
-
- private static final int BIT_INDEX_OF_16_BIT_UUID = 32;
-
- private BluetoothUuids() {}
-
- /**
- * Returns the 16-bit version of the UUID. If this is not a 16-bit UUID, throws
- * IllegalArgumentException.
- */
- public static short get16BitUuid(UUID uuid) {
- if (!is16BitUuid(uuid)) {
- throw new IllegalArgumentException("Not a 16-bit Bluetooth UUID: " + uuid);
- }
- return (short) (uuid.getMostSignificantBits() >> BIT_INDEX_OF_16_BIT_UUID);
- }
-
- /** Checks whether the UUID is 16 bit */
- public static boolean is16BitUuid(UUID uuid) {
- // See Service Discovery Protocol in the Bluetooth Core Specification. Bits at index 32-48
- // are the 16-bit UUID, and the rest must match the Base UUID.
- return uuid.getLeastSignificantBits() == BASE_UUID.getLeastSignificantBits()
- && (uuid.getMostSignificantBits() & 0xFFFF0000FFFFFFFFL)
- == BASE_UUID.getMostSignificantBits();
- }
-
- /** Converts short UUID to 128 bit UUID */
- public static UUID to128BitUuid(short shortUuid) {
- return new UUID(
- ((shortUuid & 0xFFFFL) << BIT_INDEX_OF_16_BIT_UUID)
- | BASE_UUID.getMostSignificantBits(), BASE_UUID.getLeastSignificantBits());
- }
-
- /** Transfers the 16-bit Fast Pair custom GATT characteristics to 128-bit. */
- public static UUID toFastPair128BitUuid(short shortUuid) {
- return new UUID(
- ((shortUuid & 0xFFFFL) << BIT_INDEX_OF_16_BIT_UUID)
- | FAST_PAIR_BASE_UUID.getMostSignificantBits(),
- FAST_PAIR_BASE_UUID.getLeastSignificantBits());
- }
-}
diff --git a/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/BroadcastConstants.java b/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/BroadcastConstants.java
deleted file mode 100644
index c26c6adf958075a49118c69100249456b29fc6c8..0000000000000000000000000000000000000000
--- a/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/BroadcastConstants.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.nearby.common.bluetooth.fastpair;
-
-/**
- * Constants to share with the cloud syncing process.
- */
-public class BroadcastConstants {
-
- // TODO: Set right value for AOSP.
- /** Package name of the cloud syncing logic. */
- public static final String PACKAGE_NAME = "PACKAGE_NAME";
- /** Service name of the cloud syncing instance. */
- public static final String SERVICE_NAME = PACKAGE_NAME + ".SERVICE_NAME";
- private static final String PREFIX = PACKAGE_NAME + ".PREFIX_NAME.";
-
- /** Action when a fast pair device is added. */
- public static final String ACTION_FAST_PAIR_DEVICE_ADDED =
- PREFIX + "ACTION_FAST_PAIR_DEVICE_ADDED";
- /**
- * The BLE address of a device. BLE is used here instead of public because the caller of the
- * library never knows what the device's public address is.
- */
- public static final String EXTRA_ADDRESS = PREFIX + "BLE_ADDRESS";
- /** The public address of a device. */
- public static final String EXTRA_PUBLIC_ADDRESS = PREFIX + "PUBLIC_ADDRESS";
- /** Account key. */
- public static final String EXTRA_ACCOUNT_KEY = PREFIX + "ACCOUNT_KEY";
- /** Whether a paring is retroactive. */
- public static final String EXTRA_RETROACTIVE_PAIR = PREFIX + "EXTRA_RETROACTIVE_PAIR";
-
- private BroadcastConstants() {
- }
-}
diff --git a/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/Bytes.java b/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/Bytes.java
deleted file mode 100644
index 637cd03ba42c540b9e991419fdb7c4461eb8539e..0000000000000000000000000000000000000000
--- a/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/Bytes.java
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.nearby.common.bluetooth.fastpair;
-
-import androidx.annotation.Nullable;
-
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.nio.ShortBuffer;
-import java.util.Arrays;
-
-/** Represents a block of bytes, with hashCode and equals. */
-public abstract class Bytes {
- private static final char[] sHexDigits = "0123456789abcdef".toCharArray();
- private final byte[] mBytes;
-
- /**
- * A logical value consisting of one or more bytes in the given order (little-endian, i.e.
- * LSO...MSO, or big-endian, i.e. MSO...LSO). E.g. the Fast Pair Model ID is a 3-byte value,
- * and a Bluetooth device address is a 6-byte value.
- */
- public static class Value extends Bytes {
- private final ByteOrder mByteOrder;
-
- /**
- * Constructor.
- */
- public Value(byte[] bytes, ByteOrder byteOrder) {
- super(bytes);
- this.mByteOrder = byteOrder;
- }
-
- /**
- * Gets bytes.
- */
- public byte[] getBytes(ByteOrder byteOrder) {
- return this.mByteOrder.equals(byteOrder) ? getBytes() : reverse(getBytes());
- }
-
- private static byte[] reverse(byte[] bytes) {
- byte[] reversedBytes = new byte[bytes.length];
- for (int i = 0; i < bytes.length; i++) {
- reversedBytes[i] = bytes[bytes.length - i - 1];
- }
- return reversedBytes;
- }
- }
-
- Bytes(byte[] bytes) {
- mBytes = bytes;
- }
-
- private static String toHexString(byte[] bytes) {
- StringBuilder sb = new StringBuilder(2 * bytes.length);
- for (byte b : bytes) {
- sb.append(sHexDigits[(b >> 4) & 0xf]).append(sHexDigits[b & 0xf]);
- }
- return sb.toString();
- }
-
- /** Returns 2-byte values in the same order, each using the given byte order. */
- public static byte[] toBytes(ByteOrder byteOrder, short... shorts) {
- ByteBuffer byteBuffer = ByteBuffer.allocate(shorts.length * 2).order(byteOrder);
- for (short s : shorts) {
- byteBuffer.putShort(s);
- }
- return byteBuffer.array();
- }
-
- /** Returns the shorts in the same order, each converted using the given byte order. */
- static short[] toShorts(ByteOrder byteOrder, byte[] bytes) {
- ShortBuffer shortBuffer = ByteBuffer.wrap(bytes).order(byteOrder).asShortBuffer();
- short[] shorts = new short[shortBuffer.remaining()];
- shortBuffer.get(shorts);
- return shorts;
- }
-
- /** @return The bytes. */
- public byte[] getBytes() {
- return mBytes;
- }
-
- @Override
- public boolean equals(@Nullable Object o) {
- if (this == o) {
- return true;
- }
- if (!(o instanceof Bytes)) {
- return false;
- }
- Bytes that = (Bytes) o;
- return Arrays.equals(mBytes, that.mBytes);
- }
-
- @Override
- public int hashCode() {
- return Arrays.hashCode(mBytes);
- }
-
- @Override
- public String toString() {
- return toHexString(mBytes);
- }
-}
diff --git a/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/ConnectException.java b/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/ConnectException.java
deleted file mode 100644
index 9c8d292b2c1fed08ebca315a40730d75dce24f42..0000000000000000000000000000000000000000
--- a/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/ConnectException.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.nearby.common.bluetooth.fastpair;
-
-import com.android.server.nearby.intdefs.FastPairEventIntDefs.ConnectErrorCode;
-
-
-/** Thrown when connecting to a bluetooth device fails. */
-public class ConnectException extends PairingException {
- final @ConnectErrorCode int mErrorCode;
-
- ConnectException(@ConnectErrorCode int errorCode, String format, Object... objects) {
- super(format, objects);
- this.mErrorCode = errorCode;
- }
-
- /** Returns error code. */
- public @ConnectErrorCode int getErrorCode() {
- return mErrorCode;
- }
-}
diff --git a/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/Constants.java b/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/Constants.java
deleted file mode 100644
index cfecd2f5be5a69400b8a8aae547f009ffa8ee41a..0000000000000000000000000000000000000000
--- a/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/Constants.java
+++ /dev/null
@@ -1,703 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.nearby.common.bluetooth.fastpair;
-
-import static android.bluetooth.BluetoothProfile.A2DP;
-import static android.bluetooth.BluetoothProfile.HEADSET;
-
-import static com.android.server.nearby.common.bluetooth.fastpair.BluetoothUuids.to128BitUuid;
-import static com.android.server.nearby.common.bluetooth.fastpair.BluetoothUuids.toFastPair128BitUuid;
-
-import static com.google.common.primitives.Bytes.concat;
-
-import android.bluetooth.BluetoothA2dp;
-import android.bluetooth.BluetoothHeadset;
-import android.util.Log;
-
-import androidx.annotation.IntDef;
-
-import com.android.server.nearby.common.bluetooth.BluetoothException;
-import com.android.server.nearby.common.bluetooth.gatt.BluetoothGattConnection;
-
-import com.google.common.base.Preconditions;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.primitives.Shorts;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.nio.ByteBuffer;
-import java.security.GeneralSecurityException;
-import java.util.Random;
-import java.util.UUID;
-
-/**
- * Fast Pair and Transport Discovery Service constants.
- *
- *
Unless otherwise specified, these numbers come from
- * {https://www.bluetooth.com/specifications/gatt}.
- */
-public final class Constants {
-
- /** A2DP sink service uuid. */
- public static final short A2DP_SINK_SERVICE_UUID = 0x110B;
-
- /** Headset service uuid. */
- public static final short HEADSET_SERVICE_UUID = 0x1108;
-
- /** Hands free sink service uuid. */
- public static final short HANDS_FREE_SERVICE_UUID = 0x111E;
-
- /** Bluetooth address length. */
- public static final int BLUETOOTH_ADDRESS_LENGTH = 6;
-
- private static final String TAG = Constants.class.getSimpleName();
-
- /**
- * Defined by https://developers.google.com/nearby/fast-pair/spec.
- */
- public static final class FastPairService {
-
- /** Fast Pair service UUID. */
- public static final UUID ID = to128BitUuid((short) 0xFE2C);
-
- /**
- * Characteristic to write verification bytes to during the key handshake.
- */
- public static final class KeyBasedPairingCharacteristic {
-
- private static final short SHORT_UUID = 0x1234;
-
- /**
- * Gets the new 128-bit UUID of this characteristic.
- *
- *
Note: For GATT server only. GATT client should use {@link
- * KeyBasedPairingCharacteristic#getId(BluetoothGattConnection)}.
- */
- public static final UUID CUSTOM_128_BIT_UUID = toFastPair128BitUuid(SHORT_UUID);
-
- /**
- * Gets the {@link UUID} of this characteristic.
- *
- *
This method is designed for being backward compatible with old version of UUID
- * therefore needs the {@link BluetoothGattConnection} parameter to check the supported
- * status of the Fast Pair provider.
- */
- public static UUID getId(BluetoothGattConnection gattConnection) {
- return getSupportedUuid(gattConnection, SHORT_UUID);
- }
-
- /**
- * Constants related to the decrypted request written to this characteristic.
- */
- public static final class Request {
-
- /**
- * The size of this message.
- */
- public static final int SIZE = 16;
-
- /**
- * The index of this message for indicating the type byte.
- */
- public static final int TYPE_INDEX = 0;
-
- /**
- * The index of this message for indicating the flags byte.
- */
- public static final int FLAGS_INDEX = 1;
-
- /**
- * The index of this message for indicating the verification data start from.
- */
- public static final int VERIFICATION_DATA_INDEX = 2;
-
- /**
- * The length of verification data, it is Provider’s current BLE address or public
- * address.
- */
- public static final int VERIFICATION_DATA_LENGTH = BLUETOOTH_ADDRESS_LENGTH;
-
- /**
- * The index of this message for indicating the seeker's public address start from.
- */
- public static final int SEEKER_PUBLIC_ADDRESS_INDEX = 8;
-
- /**
- * The index of this message for indicating event group.
- */
- public static final int EVENT_GROUP_INDEX = 8;
-
- /**
- * The index of this message for indicating event code.
- */
- public static final int EVENT_CODE_INDEX = 9;
-
- /**
- * The index of this message for indicating the length of additional data of the
- * event.
- */
- public static final int EVENT_ADDITIONAL_DATA_LENGTH_INDEX = 10;
-
- /**
- * The index of this message for indicating the event additional data start from.
- */
- public static final int EVENT_ADDITIONAL_DATA_INDEX = 11;
-
- /**
- * The index of this message for indicating the additional data type used in the
- * following Additional Data characteristic.
- */
- public static final int ADDITIONAL_DATA_TYPE_INDEX = 10;
-
- /**
- * The type of this message for Key-based Pairing Request.
- */
- public static final byte TYPE_KEY_BASED_PAIRING_REQUEST = 0x00;
-
- /**
- * The bit indicating that the Fast Pair device should temporarily become
- * discoverable.
- */
- public static final byte REQUEST_DISCOVERABLE = (byte) (1 << 7);
-
- /**
- * The bit indicating that the requester (Seeker) has included their public address
- * in bytes [7,12] of the request, and the Provider should initiate bonding to that
- * address.
- */
- public static final byte PROVIDER_INITIATES_BONDING = (byte) (1 << 6);
-
- /**
- * The bit indicating that Seeker requests Provider shall return the existing name.
- */
- public static final byte REQUEST_DEVICE_NAME = (byte) (1 << 5);
-
- /**
- * The bit to request retroactive pairing.
- */
- public static final byte REQUEST_RETROACTIVE_PAIR = (byte) (1 << 4);
-
- /**
- * The type of this message for action over BLE.
- */
- public static final byte TYPE_ACTION_OVER_BLE = 0x10;
-
- private Request() {
- }
- }
-
- /**
- * Enumerates all flags of key-based pairing request.
- */
- @Retention(RetentionPolicy.SOURCE)
- @IntDef(
- value = {
- KeyBasedPairingRequestFlag.REQUEST_DISCOVERABLE,
- KeyBasedPairingRequestFlag.PROVIDER_INITIATES_BONDING,
- KeyBasedPairingRequestFlag.REQUEST_DEVICE_NAME,
- KeyBasedPairingRequestFlag.REQUEST_RETROACTIVE_PAIR,
- })
- public @interface KeyBasedPairingRequestFlag {
- /**
- * The bit indicating that the Fast Pair device should temporarily become
- * discoverable.
- */
- int REQUEST_DISCOVERABLE = (byte) (1 << 7);
- /**
- * The bit indicating that the requester (Seeker) has included their public address
- * in bytes [7,12] of the request, and the Provider should initiate bonding to that
- * address.
- */
- int PROVIDER_INITIATES_BONDING = (byte) (1 << 6);
- /**
- * The bit indicating that Seeker requests Provider shall return the existing name.
- */
- int REQUEST_DEVICE_NAME = (byte) (1 << 5);
- /**
- * The bit indicating that the Seeker request retroactive pairing.
- */
- int REQUEST_RETROACTIVE_PAIR = (byte) (1 << 4);
- }
-
- /**
- * Enumerates all flags of action over BLE request, see Fast Pair spec for details.
- */
- @IntDef(
- value = {
- ActionOverBleFlag.DEVICE_ACTION,
- ActionOverBleFlag.ADDITIONAL_DATA_CHARACTERISTIC,
- })
- public @interface ActionOverBleFlag {
- /**
- * The bit indicating that the handshaking is for Device Action.
- */
- int DEVICE_ACTION = (byte) (1 << 7);
- /**
- * The bit indicating that this handshake will be followed by Additional Data
- * characteristic.
- */
- int ADDITIONAL_DATA_CHARACTERISTIC = (byte) (1 << 6);
- }
-
-
- /**
- * Constants related to the decrypted response sent back in a notify.
- */
- public static final class Response {
-
- /**
- * The type of this message = Key-based Pairing Response.
- */
- public static final byte TYPE = 0x01;
-
- private Response() {
- }
- }
-
- private KeyBasedPairingCharacteristic() {
- }
- }
-
- /**
- * Characteristic used during Key-based Pairing, to exchange the encrypted passkey.
- */
- public static final class PasskeyCharacteristic {
-
- private static final short SHORT_UUID = 0x1235;
-
- /**
- * Gets the new 128-bit UUID of this characteristic.
- *
- *
Note: For GATT server only. GATT client should use {@link
- * PasskeyCharacteristic#getId(BluetoothGattConnection)}.
- */
- public static final UUID CUSTOM_128_BIT_UUID = toFastPair128BitUuid(SHORT_UUID);
-
- /**
- * Gets the {@link UUID} of this characteristic.
- *
- *
This method is designed for being backward compatible with old version of UUID
- * therefore
- * needs the {@link BluetoothGattConnection} parameter to check the supported status of
- * the Fast Pair provider.
- */
- public static UUID getId(BluetoothGattConnection gattConnection) {
- return getSupportedUuid(gattConnection, SHORT_UUID);
- }
-
- /**
- * The type of the Passkey Block message.
- */
- @IntDef(
- value = {
- Type.SEEKER,
- Type.PROVIDER,
- })
- public @interface Type {
- /**
- * Seeker's Passkey.
- */
- int SEEKER = (byte) 0x02;
- /**
- * Provider's Passkey.
- */
- int PROVIDER = (byte) 0x03;
- }
-
- /**
- * Constructs the encrypted value to write to the characteristic.
- */
- public static byte[] encrypt(@Type int type, byte[] secret, int passkey)
- throws GeneralSecurityException {
- Preconditions.checkArgument(
- 0 < passkey && passkey < /*2^24=*/ 16777216,
- "Passkey %s must be positive and fit in 3 bytes",
- passkey);
- byte[] passkeyBytes =
- new byte[]{(byte) (passkey >>> 16), (byte) (passkey >>> 8), (byte) passkey};
- byte[] salt =
- new byte[AesEcbSingleBlockEncryption.AES_BLOCK_LENGTH - 1
- - passkeyBytes.length];
- new Random().nextBytes(salt);
- return AesEcbSingleBlockEncryption.encrypt(
- secret, concat(new byte[]{(byte) type}, passkeyBytes, salt));
- }
-
- /**
- * Extracts the passkey from the encrypted characteristic value.
- */
- public static int decrypt(@Type int type, byte[] secret,
- byte[] passkeyCharacteristicValue)
- throws GeneralSecurityException {
- byte[] decrypted = AesEcbSingleBlockEncryption
- .decrypt(secret, passkeyCharacteristicValue);
- if (decrypted[0] != (byte) type) {
- throw new GeneralSecurityException(
- "Wrong Passkey Block type (expected " + type + ", got "
- + decrypted[0] + ")");
- }
- return ByteBuffer.allocate(4)
- .put((byte) 0)
- .put(decrypted, /*offset=*/ 1, /*length=*/ 3)
- .getInt(0);
- }
-
- private PasskeyCharacteristic() {
- }
- }
-
- /**
- * Characteristic to write to during the key exchange.
- */
- public static final class AccountKeyCharacteristic {
-
- private static final short SHORT_UUID = 0x1236;
-
- /**
- * Gets the new 128-bit UUID of this characteristic.
- *
- *
Note: For GATT server only. GATT client should use {@link
- * AccountKeyCharacteristic#getId(BluetoothGattConnection)}.
- */
- public static final UUID CUSTOM_128_BIT_UUID = toFastPair128BitUuid(SHORT_UUID);
-
- /**
- * Gets the {@link UUID} of this characteristic.
- *
- *
This method is designed for being backward compatible with old version of UUID
- * therefore
- * needs the {@link BluetoothGattConnection} parameter to check the supported status of
- * the Fast Pair provider.
- */
- public static UUID getId(BluetoothGattConnection gattConnection) {
- return getSupportedUuid(gattConnection, SHORT_UUID);
- }
-
- /**
- * The type for this message, account key request.
- */
- public static final byte TYPE = 0x04;
-
- private AccountKeyCharacteristic() {
- }
- }
-
- /**
- * Characteristic to write to and notify on for handling personalized name, see {@link
- * NamingEncoder}.
- */
- public static final class NameCharacteristic {
-
- private static final short SHORT_UUID = 0x1237;
-
- /**
- * Gets the new 128-bit UUID of this characteristic.
- *
- *
Note: For GATT server only. GATT client should use {@link
- * NameCharacteristic#getId(BluetoothGattConnection)}.
- */
- public static final UUID CUSTOM_128_BIT_UUID = toFastPair128BitUuid(SHORT_UUID);
-
- /**
- * Gets the {@link UUID} of this characteristic.
- *
- *
This method is designed for being backward compatible with old version of UUID
- * therefore
- * needs the {@link BluetoothGattConnection} parameter to check the supported status of
- * the Fast Pair provider.
- */
- public static UUID getId(BluetoothGattConnection gattConnection) {
- return getSupportedUuid(gattConnection, SHORT_UUID);
- }
-
- private NameCharacteristic() {
- }
- }
-
- /**
- * Characteristic to write to and notify on for handling additional data, see
- * https://developers.google.com/nearby/fast-pair/early-access/spec#AdditionalData
- */
- public static final class AdditionalDataCharacteristic {
-
- private static final short SHORT_UUID = 0x1237;
-
- public static final int DATA_ID_INDEX = 0;
- public static final int DATA_LENGTH_INDEX = 1;
- public static final int DATA_START_INDEX = 2;
-
- /**
- * Gets the new 128-bit UUID of this characteristic.
- *
- *
Note: For GATT server only. GATT client should use {@link
- * AdditionalDataCharacteristic#getId(BluetoothGattConnection)}.
- */
- public static final UUID CUSTOM_128_BIT_UUID = toFastPair128BitUuid(SHORT_UUID);
-
- /**
- * Gets the {@link UUID} of this characteristic.
- *
- *
This method is designed for being backward compatible with old version of UUID
- * therefore
- * needs the {@link BluetoothGattConnection} parameter to check the supported status of
- * the Fast Pair provider.
- */
- public static UUID getId(BluetoothGattConnection gattConnection) {
- return getSupportedUuid(gattConnection, SHORT_UUID);
- }
-
- /**
- * Enumerates all types of additional data.
- */
- @Retention(RetentionPolicy.SOURCE)
- @IntDef(
- value = {
- AdditionalDataType.PERSONALIZED_NAME,
- AdditionalDataType.UNKNOWN,
- })
- public @interface AdditionalDataType {
- /**
- * The value indicating that the type is for personalized name.
- */
- int PERSONALIZED_NAME = (byte) 0x01;
- int UNKNOWN = (byte) 0x00; // and all others.
- }
- }
-
- /**
- * Characteristic to control the beaconing feature (FastPair+Eddystone).
- */
- public static final class BeaconActionsCharacteristic {
-
- private static final short SHORT_UUID = 0x1238;
-
- /**
- * Gets the new 128-bit UUID of this characteristic.
- *
- *
Note: For GATT server only. GATT client should use {@link
- * BeaconActionsCharacteristic#getId(BluetoothGattConnection)}.
- */
- public static final UUID CUSTOM_128_BIT_UUID = toFastPair128BitUuid(SHORT_UUID);
-
- /**
- * Gets the {@link UUID} of this characteristic.
- *
- *
This method is designed for being backward compatible with old version of UUID
- * therefore
- * needs the {@link BluetoothGattConnection} parameter to check the supported status of
- * the Fast Pair provider.
- */
- public static UUID getId(BluetoothGattConnection gattConnection) {
- return getSupportedUuid(gattConnection, SHORT_UUID);
- }
-
- /**
- * Enumerates all types of beacon actions.
- */
- /** Fast Pair Bond State. */
- @Retention(RetentionPolicy.SOURCE)
- @IntDef(
- value = {
- BeaconActionType.READ_BEACON_PARAMETERS,
- BeaconActionType.READ_PROVISIONING_STATE,
- BeaconActionType.SET_EPHEMERAL_IDENTITY_KEY,
- BeaconActionType.CLEAR_EPHEMERAL_IDENTITY_KEY,
- BeaconActionType.READ_EPHEMERAL_IDENTITY_KEY,
- BeaconActionType.RING,
- BeaconActionType.READ_RINGING_STATE,
- BeaconActionType.UNKNOWN,
- })
- public @interface BeaconActionType {
- int READ_BEACON_PARAMETERS = (byte) 0x00;
- int READ_PROVISIONING_STATE = (byte) 0x01;
- int SET_EPHEMERAL_IDENTITY_KEY = (byte) 0x02;
- int CLEAR_EPHEMERAL_IDENTITY_KEY = (byte) 0x03;
- int READ_EPHEMERAL_IDENTITY_KEY = (byte) 0x04;
- int RING = (byte) 0x05;
- int READ_RINGING_STATE = (byte) 0x06;
- int UNKNOWN = (byte) 0xFF; // and all others
- }
-
- /** Converts value to enum. */
- public static @BeaconActionType int valueOf(byte value) {
- switch(value) {
- case BeaconActionType.READ_BEACON_PARAMETERS:
- case BeaconActionType.READ_PROVISIONING_STATE:
- case BeaconActionType.SET_EPHEMERAL_IDENTITY_KEY:
- case BeaconActionType.CLEAR_EPHEMERAL_IDENTITY_KEY:
- case BeaconActionType.READ_EPHEMERAL_IDENTITY_KEY:
- case BeaconActionType.RING:
- case BeaconActionType.READ_RINGING_STATE:
- case BeaconActionType.UNKNOWN:
- return value;
- default:
- return BeaconActionType.UNKNOWN;
- }
- }
- }
-
-
- /**
- * Characteristic to read for checking firmware version. 0X2A26 is assigned number from
- * bluetooth SIG website.
- */
- public static final class FirmwareVersionCharacteristic {
-
- /** UUID for firmware version. */
- public static final UUID ID = to128BitUuid((short) 0x2A26);
-
- private FirmwareVersionCharacteristic() {
- }
- }
-
- private FastPairService() {
- }
- }
-
- /**
- * Defined by the BR/EDR Handover Profile. Pre-release version here:
- * {https://jfarfel.users.x20web.corp.google.com/Bluetooth%20Handover%20d09.pdf}
- */
- public interface TransportDiscoveryService {
-
- UUID ID = to128BitUuid((short) 0x1824);
-
- byte BLUETOOTH_SIG_ORGANIZATION_ID = 0x01;
- byte SERVICE_UUIDS_16_BIT_LIST_TYPE = 0x01;
- byte SERVICE_UUIDS_32_BIT_LIST_TYPE = 0x02;
- byte SERVICE_UUIDS_128_BIT_LIST_TYPE = 0x03;
-
- /**
- * Writing to this allows you to activate the BR/EDR transport.
- */
- interface ControlPointCharacteristic {
-
- UUID ID = to128BitUuid((short) 0x2ABC);
- byte ACTIVATE_TRANSPORT_OP_CODE = 0x01;
- }
-
- /**
- * Info necessary to pair (mostly the Bluetooth Address).
- */
- interface BrHandoverDataCharacteristic {
-
- UUID ID = to128BitUuid((short) 0x2C01);
-
- /**
- * All bits are reserved for future use.
- */
- byte BR_EDR_FEATURES = 0x00;
- }
-
- /**
- * This characteristic exists only to wrap the descriptor.
- */
- interface BluetoothSigDataCharacteristic {
-
- UUID ID = to128BitUuid((short) 0x2C02);
-
- /**
- * The entire Transport Block data (e.g. supported Bluetooth services).
- */
- interface BrTransportBlockDataDescriptor {
-
- UUID ID = to128BitUuid((short) 0x2C03);
- }
- }
- }
-
- public static final UUID CLIENT_CHARACTERISTIC_CONFIGURATION_DESCRIPTOR_UUID =
- to128BitUuid((short) 0x2902);
-
- /**
- * Wrapper for Bluetooth profile
- */
- public static class Profile {
-
- public final int type;
- public final String name;
- public final String connectionStateAction;
-
- private Profile(int type, String name, String connectionStateAction) {
- this.type = type;
- this.name = name;
- this.connectionStateAction = connectionStateAction;
- }
-
- @Override
- public String toString() {
- return name;
- }
- }
-
- /**
- * {@link BluetoothHeadset} is used for both Headset and HandsFree (HFP).
- */
- private static final Profile HEADSET_AND_HANDS_FREE_PROFILE =
- new Profile(
- HEADSET, "HEADSET_AND_HANDS_FREE",
- BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED);
-
- /** Fast Pair supported profiles. */
- public static final ImmutableMap PROFILES =
- ImmutableMap.builder()
- .put(
- Constants.A2DP_SINK_SERVICE_UUID,
- new Profile(A2DP, "A2DP",
- BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED))
- .put(Constants.HEADSET_SERVICE_UUID, HEADSET_AND_HANDS_FREE_PROFILE)
- .put(Constants.HANDS_FREE_SERVICE_UUID, HEADSET_AND_HANDS_FREE_PROFILE)
- .build();
-
- static short[] getSupportedProfiles() {
- return Shorts.toArray(PROFILES.keySet());
- }
-
- /**
- * Helper method of getting 128-bit UUID for Fast Pair custom GATT characteristics.
- *
- *
This method is designed for being backward compatible with old version of UUID therefore
- * needs the {@link BluetoothGattConnection} parameter to check the supported status of the Fast
- * Pair provider.
- *
- *
Note: For new custom GATT characteristics, don't need to use this helper and please just
- * call {@code toFastPair128BitUuid(shortUuid)} to get the UUID. Which also implies that callers
- * don't need to provide {@link BluetoothGattConnection} to get the UUID anymore.
- */
- private static UUID getSupportedUuid(BluetoothGattConnection gattConnection, short shortUuid) {
- // In worst case (new characteristic not found), this method's performance impact is about
- // 6ms
- // by using Pixel2 + JBL LIVE220. And the impact should be less and less along with more and
- // more devices adopt the new characteristics.
- try {
- // Checks the new UUID first.
- if (gattConnection
- .getCharacteristic(FastPairService.ID, toFastPair128BitUuid(shortUuid))
- != null) {
- Log.d(TAG, "Uses new KeyBasedPairingCharacteristic.ID");
- return toFastPair128BitUuid(shortUuid);
- }
- } catch (BluetoothException e) {
- Log.d(TAG, "Uses old KeyBasedPairingCharacteristic.ID");
- }
- // Returns the old UUID for default.
- return to128BitUuid(shortUuid);
- }
-
- private Constants() {
- }
-}
diff --git a/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/CreateBondException.java b/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/CreateBondException.java
deleted file mode 100644
index d6aa3b2baa912b6ad6b3611ddaad7348a5ce198c..0000000000000000000000000000000000000000
--- a/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/CreateBondException.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.nearby.common.bluetooth.fastpair;
-
-import com.android.server.nearby.intdefs.FastPairEventIntDefs.CreateBondErrorCode;
-
-/** Thrown when binding (pairing) with a bluetooth device fails. */
-public class CreateBondException extends PairingException {
- final @CreateBondErrorCode int mErrorCode;
- int mReason;
-
- CreateBondException(@CreateBondErrorCode int errorCode, int reason, String format,
- Object... objects) {
- super(format, objects);
- this.mErrorCode = errorCode;
- this.mReason = reason;
- }
-
- /** Returns error code. */
- public @CreateBondErrorCode int getErrorCode() {
- return mErrorCode;
- }
-
- /** Returns reason. */
- public int getReason() {
- return mReason;
- }
-}
diff --git a/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/DeviceIntentReceiver.java b/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/DeviceIntentReceiver.java
deleted file mode 100644
index 5bcf10ab2b7278c3111566146ca739b7fd0f6b24..0000000000000000000000000000000000000000
--- a/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/DeviceIntentReceiver.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.nearby.common.bluetooth.fastpair;
-
-import static com.android.server.nearby.common.bluetooth.fastpair.BluetoothAddress.maskBluetoothAddress;
-
-import android.bluetooth.BluetoothDevice;
-import android.content.Context;
-import android.content.Intent;
-import android.util.Log;
-
-/**
- * Like {@link SimpleBroadcastReceiver}, but for intents about a certain {@link BluetoothDevice}.
- */
-abstract class DeviceIntentReceiver extends SimpleBroadcastReceiver {
-
- private static final String TAG = DeviceIntentReceiver.class.getSimpleName();
-
- private final BluetoothDevice mDevice;
-
- static DeviceIntentReceiver oneShotReceiver(
- Context context, Preferences preferences, BluetoothDevice device, String... actions) {
- return new DeviceIntentReceiver(context, preferences, device, actions) {
- @Override
- protected void onReceiveDeviceIntent(Intent intent) throws Exception {
- close();
- }
- };
- }
-
- /**
- * @param context The context to use to register / unregister the receiver.
- * @param device The interesting device. We ignore intents about other devices.
- * @param actions The actions to include in our intent filter.
- */
- protected DeviceIntentReceiver(
- Context context, Preferences preferences, BluetoothDevice device, String... actions) {
- super(context, preferences, actions);
- this.mDevice = device;
- }
-
- /**
- * Called with intents about the interesting device (see {@link #DeviceIntentReceiver}). Any
- * exception thrown by this method will be delivered via {@link #await}.
- */
- protected abstract void onReceiveDeviceIntent(Intent intent) throws Exception;
-
- // incompatible types in argument.
- @Override
- protected void onReceive(Intent intent) throws Exception {
- BluetoothDevice intentDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
- if (mDevice == null || mDevice.equals(intentDevice)) {
- onReceiveDeviceIntent(intent);
- } else {
- Log.v(TAG,
- "Ignoring intent for device=" + maskBluetoothAddress(intentDevice)
- + "(expected "
- + maskBluetoothAddress(mDevice) + ")");
- }
- }
-}
diff --git a/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/EllipticCurveDiffieHellmanExchange.java b/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/EllipticCurveDiffieHellmanExchange.java
deleted file mode 100644
index dbcdf077ea16a08167ddff513858161b33d85e88..0000000000000000000000000000000000000000
--- a/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/EllipticCurveDiffieHellmanExchange.java
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.nearby.common.bluetooth.fastpair;
-
-import static com.google.common.primitives.Bytes.concat;
-
-import androidx.annotation.Nullable;
-
-import java.math.BigInteger;
-import java.security.GeneralSecurityException;
-import java.security.KeyFactory;
-import java.security.KeyPair;
-import java.security.KeyPairGenerator;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.security.NoSuchProviderException;
-import java.security.PrivateKey;
-import java.security.PublicKey;
-import java.security.interfaces.ECPrivateKey;
-import java.security.interfaces.ECPublicKey;
-import java.security.spec.ECGenParameterSpec;
-import java.security.spec.ECParameterSpec;
-import java.security.spec.ECPoint;
-import java.security.spec.ECPrivateKeySpec;
-import java.security.spec.ECPublicKeySpec;
-import java.util.Arrays;
-
-import javax.crypto.KeyAgreement;
-
-/**
- * Helper for generating keys based off of the Elliptic-Curve Diffie-Hellman algorithm (ECDH).
- */
-public final class EllipticCurveDiffieHellmanExchange {
-
- public static final int PUBLIC_KEY_LENGTH = 64;
- static final int PRIVATE_KEY_LENGTH = 32;
-
- private static final String[] PROVIDERS = {"GmsCore_OpenSSL", "AndroidOpenSSL", "SC", "BC"};
-
- private static final String EC_ALGORITHM = "EC";
-
- /**
- * Also known as prime256v1 or NIST P-256.
- */
- private static final ECGenParameterSpec EC_GEN_PARAMS = new ECGenParameterSpec("secp256r1");
-
- @Nullable
- private final ECPublicKey mPublicKey;
- private final ECPrivateKey mPrivateKey;
-
- /**
- * Creates a new EllipticCurveDiffieHellmanExchange object.
- */
- public static EllipticCurveDiffieHellmanExchange create() throws GeneralSecurityException {
- KeyPair keyPair = generateKeyPair();
- return new EllipticCurveDiffieHellmanExchange(
- (ECPublicKey) keyPair.getPublic(), (ECPrivateKey) keyPair.getPrivate());
- }
-
- /**
- * Creates a new EllipticCurveDiffieHellmanExchange object.
- */
- public static EllipticCurveDiffieHellmanExchange create(byte[] privateKey)
- throws GeneralSecurityException {
- ECPrivateKey ecPrivateKey = (ECPrivateKey) generatePrivateKey(privateKey);
- return new EllipticCurveDiffieHellmanExchange(/*publicKey=*/ null, ecPrivateKey);
- }
-
- private EllipticCurveDiffieHellmanExchange(
- @Nullable ECPublicKey publicKey, ECPrivateKey privateKey) {
- this.mPublicKey = publicKey;
- this.mPrivateKey = privateKey;
- }
-
- /**
- * @param otherPublicKey Another party's public key. See {@link #getPublicKey()} for format.
- * @return The shared secret. Given our public key (and its private key), the other party can
- * generate the same secret. This is a key meant for symmetric encryption.
- */
- public byte[] generateSecret(byte[] otherPublicKey) throws GeneralSecurityException {
- KeyAgreement agreement = keyAgreement();
- agreement.init(mPrivateKey);
- agreement.doPhase(generatePublicKey(otherPublicKey), /*lastPhase=*/ true);
- byte[] secret = agreement.generateSecret();
- // Headsets only support AES with 128-bit keys. So, hash the secret so that the entropy is
- // high and then take only the first 128-bits.
- secret = MessageDigest.getInstance("SHA-256").digest(secret);
- return Arrays.copyOf(secret, 16);
- }
-
- /**
- * Returns a public point W on the NIST P-256 elliptic curve. First 32 bytes are the X
- * coordinate, next 32 bytes are the Y coordinate. Each coordinate is an unsigned big-endian
- * integer.
- */
- public @Nullable byte[] getPublicKey() {
- if (mPublicKey == null) {
- return null;
- }
- ECPoint w = mPublicKey.getW();
- // See getPrivateKey for why we're resizing.
- byte[] x = resizeWithLeadingZeros(w.getAffineX().toByteArray(), 32);
- byte[] y = resizeWithLeadingZeros(w.getAffineY().toByteArray(), 32);
- return concat(x, y);
- }
-
- /**
- * Returns a private value S, an unsigned big-endian integer.
- */
- public byte[] getPrivateKey() {
- // Note that BigInteger.toByteArray() returns a signed representation, so it will add an
- // extra zero byte to the front if the first bit is 1.
- // We must remove that leading zero (we know the number is unsigned). We must also add
- // leading zeros if the number is too small.
- return resizeWithLeadingZeros(mPrivateKey.getS().toByteArray(), 32);
- }
-
- /**
- * Removes or adds leading zeros until we have an array of size {@code n}.
- */
- private static byte[] resizeWithLeadingZeros(byte[] x, int n) {
- if (n < x.length) {
- int start = x.length - n;
- for (int i = 0; i < start; i++) {
- if (x[i] != 0) {
- throw new IllegalArgumentException(
- "More than " + n + " non-zero bytes in " + Arrays.toString(x));
- }
- }
- return Arrays.copyOfRange(x, start, x.length);
- }
- return concat(new byte[n - x.length], x);
- }
-
- /**
- * @param publicKey See {@link #getPublicKey()} for format.
- */
- private static PublicKey generatePublicKey(byte[] publicKey) throws GeneralSecurityException {
- if (publicKey.length != PUBLIC_KEY_LENGTH) {
- throw new GeneralSecurityException("Public key length incorrect: " + publicKey.length);
- }
- byte[] x = Arrays.copyOf(publicKey, publicKey.length / 2);
- byte[] y = Arrays.copyOfRange(publicKey, publicKey.length / 2, publicKey.length);
- return keyFactory()
- .generatePublic(
- new ECPublicKeySpec(
- new ECPoint(new BigInteger(/*signum=*/ 1, x),
- new BigInteger(/*signum=*/ 1, y)),
- ecParameterSpec()));
- }
-
- /**
- * @param privateKey See {@link #getPrivateKey()} for format.
- */
- private static PrivateKey generatePrivateKey(byte[] privateKey)
- throws GeneralSecurityException {
- if (privateKey.length != PRIVATE_KEY_LENGTH) {
- throw new GeneralSecurityException("Private key length incorrect: "
- + privateKey.length);
- }
- return keyFactory()
- .generatePrivate(
- new ECPrivateKeySpec(new BigInteger(/*signum=*/ 1, privateKey),
- ecParameterSpec()));
- }
-
- private static ECParameterSpec ecParameterSpec() throws GeneralSecurityException {
- // This seems to be the simplest way to get the curve's ECParameterSpec. Verified that it's
- // the same whether you get it from the public or private key, and that it's the same as the
- // raw params in SecAggEcUtil.getNistP256Params().
- return ((ECPublicKey) generateKeyPair().getPublic()).getParams();
- }
-
- private static KeyPair generateKeyPair() throws GeneralSecurityException {
- KeyPairGenerator generator = findProvider(p -> KeyPairGenerator.getInstance(EC_ALGORITHM,
- p));
- generator.initialize(EC_GEN_PARAMS);
- return generator.generateKeyPair();
- }
-
- private static KeyAgreement keyAgreement() throws NoSuchProviderException {
- return findProvider(p -> KeyAgreement.getInstance("ECDH", p));
- }
-
- private static KeyFactory keyFactory() throws NoSuchProviderException {
- return findProvider(p -> KeyFactory.getInstance(EC_ALGORITHM, p));
- }
-
- private interface ProviderConsumer {
-
- T tryProvider(String provider) throws NoSuchAlgorithmException, NoSuchProviderException;
- }
-
- private static T findProvider(ProviderConsumer providerConsumer)
- throws NoSuchProviderException {
- for (String provider : PROVIDERS) {
- try {
- return providerConsumer.tryProvider(provider);
- } catch (NoSuchAlgorithmException | NoSuchProviderException e) {
- // No-op
- }
- }
- throw new NoSuchProviderException();
- }
-}
diff --git a/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/Event.java b/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/Event.java
deleted file mode 100644
index 0b50dfd0092b5034ca40dc5c1d908781ae376402..0000000000000000000000000000000000000000
--- a/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/Event.java
+++ /dev/null
@@ -1,250 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.nearby.common.bluetooth.fastpair;
-
-import android.bluetooth.BluetoothDevice;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import com.android.server.nearby.intdefs.NearbyEventIntDefs.EventCode;
-
-import java.util.Objects;
-
-import javax.annotation.Nullable;
-
-/**
- * Describes events that are happening during fast pairing. EventCode is required, everything else
- * is optional.
- */
-public class Event implements Parcelable {
-
- private final @EventCode int mEventCode;
- private final long mTimestamp;
- private final Short mProfile;
- private final BluetoothDevice mBluetoothDevice;
- private final Exception mException;
-
- private Event(@EventCode int eventCode, long timestamp, @Nullable Short profile,
- @Nullable BluetoothDevice bluetoothDevice, @Nullable Exception exception) {
- mEventCode = eventCode;
- mTimestamp = timestamp;
- mProfile = profile;
- mBluetoothDevice = bluetoothDevice;
- mException = exception;
- }
-
- /**
- * Returns event code.
- */
- public @EventCode int getEventCode() {
- return mEventCode;
- }
-
- /**
- * Returns timestamp.
- */
- public long getTimestamp() {
- return mTimestamp;
- }
-
- /**
- * Returns profile.
- */
- @Nullable
- public Short getProfile() {
- return mProfile;
- }
-
- /**
- * Returns Bluetooth device.
- */
- @Nullable
- public BluetoothDevice getBluetoothDevice() {
- return mBluetoothDevice;
- }
-
- /**
- * Returns exception.
- */
- @Nullable
- public Exception getException() {
- return mException;
- }
-
- /**
- * Returns whether profile is not null.
- */
- public boolean hasProfile() {
- return getProfile() != null;
- }
-
- /**
- * Returns whether Bluetooth device is not null.
- */
- public boolean hasBluetoothDevice() {
- return getBluetoothDevice() != null;
- }
-
- /**
- * Returns a builder.
- */
- public static Builder builder() {
- return new Event.Builder();
- }
-
- /**
- * Returns whether it fails.
- */
- public boolean isFailure() {
- return getException() != null;
- }
-
- @Override
- public String toString() {
- return "Event{"
- + "eventCode=" + mEventCode + ", "
- + "timestamp=" + mTimestamp + ", "
- + "profile=" + mProfile + ", "
- + "bluetoothDevice=" + mBluetoothDevice + ", "
- + "exception=" + mException
- + "}";
- }
-
- @Override
- public boolean equals(@Nullable Object o) {
- if (o == this) {
- return true;
- }
- if (o instanceof Event) {
- Event that = (Event) o;
- return this.mEventCode == that.getEventCode()
- && this.mTimestamp == that.getTimestamp()
- && (this.mProfile == null
- ? that.getProfile() == null : this.mProfile.equals(that.getProfile()))
- && (this.mBluetoothDevice == null
- ? that.getBluetoothDevice() == null :
- this.mBluetoothDevice.equals(that.getBluetoothDevice()))
- && (this.mException == null
- ? that.getException() == null :
- this.mException.equals(that.getException()));
- }
- return false;
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(mEventCode, mTimestamp, mProfile, mBluetoothDevice, mException);
- }
-
-
- /**
- * Builder
- */
- public static class Builder {
- private @EventCode int mEventCode;
- private long mTimestamp;
- private Short mProfile;
- private BluetoothDevice mBluetoothDevice;
- private Exception mException;
-
- /**
- * Set event code.
- */
- public Builder setEventCode(@EventCode int eventCode) {
- this.mEventCode = eventCode;
- return this;
- }
-
- /**
- * Set timestamp.
- */
- public Builder setTimestamp(long timestamp) {
- this.mTimestamp = timestamp;
- return this;
- }
-
- /**
- * Set profile.
- */
- public Builder setProfile(@Nullable Short profile) {
- this.mProfile = profile;
- return this;
- }
-
- /**
- * Set Bluetooth device.
- */
- public Builder setBluetoothDevice(@Nullable BluetoothDevice device) {
- this.mBluetoothDevice = device;
- return this;
- }
-
- /**
- * Set exception.
- */
- public Builder setException(@Nullable Exception exception) {
- this.mException = exception;
- return this;
- }
-
- /**
- * Builds event.
- */
- public Event build() {
- return new Event(mEventCode, mTimestamp, mProfile, mBluetoothDevice, mException);
- }
- }
-
- @Override
- public final void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(getEventCode());
- dest.writeLong(getTimestamp());
- dest.writeValue(getProfile());
- dest.writeParcelable(getBluetoothDevice(), 0);
- dest.writeSerializable(getException());
- }
-
- @Override
- public final int describeContents() {
- return 0;
- }
-
- /**
- * Event Creator instance.
- */
- public static final Creator CREATOR =
- new Creator() {
- @Override
- /** Creates Event from Parcel. */
- public Event createFromParcel(Parcel in) {
- return Event.builder()
- .setEventCode(in.readInt())
- .setTimestamp(in.readLong())
- .setProfile((Short) in.readValue(Short.class.getClassLoader()))
- .setBluetoothDevice(
- in.readParcelable(BluetoothDevice.class.getClassLoader()))
- .setException((Exception) in.readSerializable())
- .build();
- }
-
- @Override
- /** Returns Event array. */
- public Event[] newArray(int size) {
- return new Event[size];
- }
- };
-}
diff --git a/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/EventLogger.java b/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/EventLogger.java
deleted file mode 100644
index 4fc1917a396fbd70ec925b9084b521d945680848..0000000000000000000000000000000000000000
--- a/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/EventLogger.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.nearby.common.bluetooth.fastpair;
-
-/** Logs events triggered during Fast Pairing. */
-public interface EventLogger {
-
- /** Log successful event. */
- void logEventSucceeded(Event event);
-
- /** Log failed event. */
- void logEventFailed(Event event, Exception e);
-}
diff --git a/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/EventLoggerWrapper.java b/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/EventLoggerWrapper.java
deleted file mode 100644
index 024bfdee8a94e6dc73f7dee6c099a5e4d74d8095..0000000000000000000000000000000000000000
--- a/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/EventLoggerWrapper.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.nearby.common.bluetooth.fastpair;
-
-import android.bluetooth.BluetoothDevice;
-import android.content.Context;
-
-import com.android.server.nearby.common.bluetooth.fastpair.Preferences.ExtraLoggingInformation;
-import com.android.server.nearby.intdefs.NearbyEventIntDefs.EventCode;
-
-import javax.annotation.Nullable;
-
-/**
- * Convenience wrapper around EventLogger.
- */
-// TODO(b/202559985): cleanup EventLoggerWrapper.
-class EventLoggerWrapper {
-
- EventLoggerWrapper(@Nullable EventLogger eventLogger) {
- }
-
- /**
- * Binds to the logging service. This operation blocks until binding has completed or timed
- * out.
- */
- void bind(
- Context context, String address,
- @Nullable ExtraLoggingInformation extraLoggingInformation) {
- }
-
- boolean isBound() {
- return false;
- }
-
- void unbind(Context context) {
- }
-
- void setCurrentEvent(@EventCode int code) {
- }
-
- void setCurrentProfile(short profile) {
- }
-
- void logCurrentEventFailed(Exception e) {
- }
-
- void logCurrentEventSucceeded() {
- }
-
- void setDevice(@Nullable BluetoothDevice device) {
- }
-
- boolean isCurrentEvent() {
- return false;
- }
-}
diff --git a/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/FastPairConnection.java b/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/FastPairConnection.java
deleted file mode 100644
index c963aa6076879afccddab03adeee4bf3c4947e27..0000000000000000000000000000000000000000
--- a/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/FastPairConnection.java
+++ /dev/null
@@ -1,216 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.nearby.common.bluetooth.fastpair;
-
-import android.annotation.WorkerThread;
-import android.bluetooth.BluetoothDevice;
-
-import androidx.annotation.Nullable;
-import androidx.core.util.Consumer;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.server.nearby.common.bluetooth.BluetoothException;
-
-import java.security.GeneralSecurityException;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Objects;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeoutException;
-
-/** Abstract class for pairing or connecting via FastPair. */
-public abstract class FastPairConnection {
- @Nullable protected OnPairedCallback mPairedCallback;
- @Nullable protected OnGetBluetoothAddressCallback mOnGetBluetoothAddressCallback;
- @Nullable protected PasskeyConfirmationHandler mPasskeyConfirmationHandler;
- @Nullable protected FastPairSignalChecker mFastPairSignalChecker;
- @Nullable protected Consumer mRescueFromError;
- @Nullable protected Runnable mPrepareCreateBondCallback;
- protected boolean mPasskeyIsGotten;
-
- /** Sets a callback to be invoked once the device is paired. */
- public void setOnPairedCallback(OnPairedCallback callback) {
- this.mPairedCallback = callback;
- }
-
- /** Sets a callback to be invoked while the target bluetooth address is decided. */
- public void setOnGetBluetoothAddressCallback(OnGetBluetoothAddressCallback callback) {
- this.mOnGetBluetoothAddressCallback = callback;
- }
-
- /** Sets a callback to be invoked while handling the passkey confirmation. */
- public void setPasskeyConfirmationHandler(
- PasskeyConfirmationHandler passkeyConfirmationHandler) {
- this.mPasskeyConfirmationHandler = passkeyConfirmationHandler;
- }
-
- public void setFastPairSignalChecker(FastPairSignalChecker fastPairSignalChecker) {
- this.mFastPairSignalChecker = fastPairSignalChecker;
- }
-
- public void setRescueFromError(Consumer rescueFromError) {
- this.mRescueFromError = rescueFromError;
- }
-
- public void setPrepareCreateBondCallback(Runnable runnable) {
- this.mPrepareCreateBondCallback = runnable;
- }
-
- @VisibleForTesting
- @Nullable
- public Runnable getPrepareCreateBondCallback() {
- return mPrepareCreateBondCallback;
- }
-
- /**
- * Sets the fast pair history for identifying whether or not the provider has paired with the
- * primary account on other phones before.
- */
- @WorkerThread
- public abstract void setFastPairHistory(List fastPairHistoryItem);
-
- /** Sets the device name to the Provider. */
- public abstract void setProviderDeviceName(String deviceName);
-
- /** Gets the device name from the Provider. */
- @Nullable
- public abstract String getProviderDeviceName();
-
- /**
- * Gets the existing account key of the Provider.
- *
- * @return the existing account key if the Provider has paired with the account, null otherwise
- */
- @WorkerThread
- @Nullable
- public abstract byte[] getExistingAccountKey();
-
- /**
- * Pairs with Provider. Synchronous: Blocks until paired and connected. Throws on any error.
- *
- * @return the secret key for the user's account, if written
- */
- @WorkerThread
- @Nullable
- public abstract SharedSecret pair()
- throws BluetoothException, InterruptedException, TimeoutException, ExecutionException,
- PairingException, ReflectionException;
-
- /**
- * Pairs with Provider. Synchronous: Blocks until paired and connected. Throws on any error.
- *
- * @param key can be in two different formats. If it is 16 bytes long, then it is an AES account
- * key. Otherwise, it's a public key generated by {@link EllipticCurveDiffieHellmanExchange}.
- * See go/fast-pair-2-spec for how each of these keys are used.
- * @return the secret key for the user's account, if written
- */
- @WorkerThread
- @Nullable
- public abstract SharedSecret pair(@Nullable byte[] key)
- throws BluetoothException, InterruptedException, TimeoutException, ExecutionException,
- PairingException, GeneralSecurityException, ReflectionException;
-
- /** Unpairs with Provider. Synchronous: Blocks until unpaired. Throws on any error. */
- @WorkerThread
- public abstract void unpair(BluetoothDevice device)
- throws InterruptedException, TimeoutException, ExecutionException, PairingException,
- ReflectionException;
-
- /** Gets the public address of the Provider. */
- @Nullable
- public abstract String getPublicAddress();
-
-
- /** Callback for getting notifications when pairing has completed. */
- public interface OnPairedCallback {
- /** Called when the device at address has finished pairing. */
- void onPaired(String address);
- }
-
- /** Callback for getting bluetooth address Bisto oobe need this information */
- public interface OnGetBluetoothAddressCallback {
- /** Called when the device has received bluetooth address. */
- void onGetBluetoothAddress(String address);
- }
-
- /** Holds the exchanged secret key and the public mac address of the device. */
- public static class SharedSecret {
- private final byte[] mKey;
- private final String mAddress;
- private SharedSecret(byte[] key, String address) {
- mKey = key;
- mAddress = address;
- }
-
- /** Creates Shared Secret. */
- public static SharedSecret create(byte[] key, String address) {
- return new SharedSecret(key, address);
- }
-
- /** Gets Shared Secret Key. */
- public byte[] getKey() {
- return mKey;
- }
-
- /** Gets Shared Secret Address. */
- public String getAddress() {
- return mAddress;
- }
-
- @Override
- public String toString() {
- return "SharedSecret{"
- + "key=" + Arrays.toString(mKey) + ", "
- + "address=" + mAddress
- + "}";
- }
-
- @Override
- public boolean equals(@Nullable Object o) {
- if (o == this) {
- return true;
- }
- if (o instanceof SharedSecret) {
- SharedSecret that = (SharedSecret) o;
- return Arrays.equals(this.mKey, that.getKey())
- && this.mAddress.equals(that.getAddress());
- }
- return false;
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(Arrays.hashCode(mKey), mAddress);
- }
- }
-
- /** Invokes if gotten the passkey. */
- public void setPasskeyIsGotten() {
- mPasskeyIsGotten = true;
- }
-
- /** Returns the value of passkeyIsGotten. */
- public boolean getPasskeyIsGotten() {
- return mPasskeyIsGotten;
- }
-
- /** Interface to get latest address of ModelId. */
- public interface FastPairSignalChecker {
- /** Gets address of ModelId. */
- String getValidAddressForModelId(String currentDevice);
- }
-}
diff --git a/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/FastPairConstants.java b/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/FastPairConstants.java
deleted file mode 100644
index 0ff1bf2fc4780ff379ace95d20c1100f6b066711..0000000000000000000000000000000000000000
--- a/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/FastPairConstants.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.nearby.common.bluetooth.fastpair;
-
-import android.bluetooth.BluetoothDevice;
-
-/** Constants to share with other team. */
-public class FastPairConstants {
- private static final String PACKAGE_NAME = "com.android.server.nearby";
- private static final String PREFIX = PACKAGE_NAME + ".common.bluetooth.fastpair.";
-
- /** MODEL_ID item name for extended intent field. */
- public static final String EXTRA_MODEL_ID = PREFIX + "MODEL_ID";
- /** CONNECTION_ID item name for extended intent field. */
- public static final String EXTRA_CONNECTION_ID = PREFIX + "CONNECTION_ID";
- /** BLUETOOTH_MAC_ADDRESS item name for extended intent field. */
- public static final String EXTRA_BLUETOOTH_MAC_ADDRESS = PREFIX + "BLUETOOTH_MAC_ADDRESS";
- /** COMPANION_SCAN_ITEM item name for extended intent field. */
- public static final String EXTRA_SCAN_ITEM = PREFIX + "COMPANION_SCAN_ITEM";
- /** BOND_RESULT item name for extended intent field. */
- public static final String EXTRA_BOND_RESULT = PREFIX + "EXTRA_BOND_RESULT";
-
- /**
- * The bond result of the {@link BluetoothDevice} when FastPair launches the companion app, it
- * means device is BONDED but the pairing process is not triggered by FastPair.
- */
- public static final int BOND_RESULT_SUCCESS_WITHOUT_FP = 0;
-
- /**
- * The bond result of the {@link BluetoothDevice} when FastPair launches the companion app, it
- * means device is BONDED and the pairing process is triggered by FastPair.
- */
- public static final int BOND_RESULT_SUCCESS_WITH_FP = 1;
-
- /**
- * The bond result of the {@link BluetoothDevice} when FastPair launches the companion app, it
- * means the pairing process triggered by FastPair is failed due to the lack of PIN code.
- */
- public static final int BOND_RESULT_FAIL_WITH_FP_WITHOUT_PIN = 2;
-
- /**
- * The bond result of the {@link BluetoothDevice} when FastPair launches the companion app, it
- * means the pairing process triggered by FastPair is failed due to the PIN code is not
- * confirmed by the user.
- */
- public static final int BOND_RESULT_FAIL_WITH_FP_WITH_PIN_NOT_CONFIRMED = 3;
-
- /**
- * The bond result of the {@link BluetoothDevice} when FastPair launches the companion app, it
- * means the pairing process triggered by FastPair is failed due to the user thinks the PIN is
- * wrong.
- */
- public static final int BOND_RESULT_FAIL_WITH_FP_WITH_PIN_WRONG = 4;
-
- /**
- * The bond result of the {@link BluetoothDevice} when FastPair launches the companion app, it
- * means the pairing process triggered by FastPair is failed even after the user confirmed the
- * PIN code is correct.
- */
- public static final int BOND_RESULT_FAIL_WITH_FP_WITH_PIN_CORRECT = 5;
-
- private FastPairConstants() {}
-}
diff --git a/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/FastPairDualConnection.java b/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/FastPairDualConnection.java
deleted file mode 100644
index 789ef5989fa02d5770779d8357dd7a59f4c3d181..0000000000000000000000000000000000000000
--- a/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/FastPairDualConnection.java
+++ /dev/null
@@ -1,2127 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.nearby.common.bluetooth.fastpair;
-
-import static android.bluetooth.BluetoothDevice.BOND_BONDED;
-import static android.bluetooth.BluetoothDevice.BOND_BONDING;
-import static android.bluetooth.BluetoothDevice.BOND_NONE;
-
-import static com.android.server.nearby.common.bluetooth.fastpair.BluetoothAddress.maskBluetoothAddress;
-import static com.android.server.nearby.common.bluetooth.fastpair.BluetoothUuids.get16BitUuid;
-import static com.android.server.nearby.common.bluetooth.fastpair.BluetoothUuids.to128BitUuid;
-import static com.android.server.nearby.common.bluetooth.fastpair.Bytes.toBytes;
-import static com.android.server.nearby.common.bluetooth.fastpair.Bytes.toShorts;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.base.Verify.verifyNotNull;
-import static com.google.common.io.BaseEncoding.base16;
-import static com.google.common.primitives.Bytes.concat;
-
-import android.bluetooth.BluetoothDevice;
-import android.bluetooth.BluetoothGattCharacteristic;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.os.ParcelUuid;
-import android.os.SystemClock;
-import android.text.TextUtils;
-import android.util.Log;
-
-import androidx.annotation.GuardedBy;
-import androidx.annotation.IntDef;
-import androidx.annotation.Nullable;
-import androidx.annotation.VisibleForTesting;
-import androidx.annotation.WorkerThread;
-
-import com.android.server.nearby.common.bluetooth.BluetoothException;
-import com.android.server.nearby.common.bluetooth.BluetoothGattException;
-import com.android.server.nearby.common.bluetooth.BluetoothTimeoutException;
-import com.android.server.nearby.common.bluetooth.fastpair.BluetoothAudioPairer.KeyBasedPairingInfo;
-import com.android.server.nearby.common.bluetooth.fastpair.Constants.FastPairService;
-import com.android.server.nearby.common.bluetooth.fastpair.Constants.FastPairService.AccountKeyCharacteristic;
-import com.android.server.nearby.common.bluetooth.fastpair.Constants.FastPairService.AdditionalDataCharacteristic.AdditionalDataType;
-import com.android.server.nearby.common.bluetooth.fastpair.Constants.FastPairService.FirmwareVersionCharacteristic;
-import com.android.server.nearby.common.bluetooth.fastpair.Constants.FastPairService.KeyBasedPairingCharacteristic.KeyBasedPairingRequestFlag;
-import com.android.server.nearby.common.bluetooth.fastpair.Constants.FastPairService.NameCharacteristic;
-import com.android.server.nearby.common.bluetooth.fastpair.Constants.TransportDiscoveryService;
-import com.android.server.nearby.common.bluetooth.fastpair.HandshakeHandler.ActionOverBle;
-import com.android.server.nearby.common.bluetooth.fastpair.HandshakeHandler.HandshakeException;
-import com.android.server.nearby.common.bluetooth.fastpair.HandshakeHandler.HandshakeMessage;
-import com.android.server.nearby.common.bluetooth.fastpair.HandshakeHandler.KeyBasedPairingRequest;
-import com.android.server.nearby.common.bluetooth.fastpair.Ltv.ParseException;
-import com.android.server.nearby.common.bluetooth.fastpair.TimingLogger.ScopedTiming;
-import com.android.server.nearby.common.bluetooth.gatt.BluetoothGattConnection;
-import com.android.server.nearby.common.bluetooth.gatt.BluetoothGattConnection.ChangeObserver;
-import com.android.server.nearby.common.bluetooth.testability.android.bluetooth.BluetoothAdapter;
-import com.android.server.nearby.common.bluetooth.util.BluetoothOperationExecutor.BluetoothOperationTimeoutException;
-import com.android.server.nearby.common.locator.Locator;
-import com.android.server.nearby.fastpair.FastPairController;
-import com.android.server.nearby.intdefs.FastPairEventIntDefs.BrEdrHandoverErrorCode;
-import com.android.server.nearby.intdefs.FastPairEventIntDefs.ConnectErrorCode;
-import com.android.server.nearby.intdefs.FastPairEventIntDefs.CreateBondErrorCode;
-import com.android.server.nearby.intdefs.FastPairEventIntDefs.ErrorCode;
-import com.android.server.nearby.intdefs.NearbyEventIntDefs.EventCode;
-
-import com.google.common.base.Ascii;
-import com.google.common.base.Preconditions;
-import com.google.common.primitives.Shorts;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.nio.ByteOrder;
-import java.security.GeneralSecurityException;
-import java.security.NoSuchAlgorithmException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Locale;
-import java.util.Set;
-import java.util.UUID;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-/**
- * Supports Fast Pair pairing with certain Bluetooth headphones, Auto, etc.
- *
- *
Based on https://developers.google.com/nearby/fast-pair/spec, the pairing is constructed by
- * both BLE and BREDR connections. Example state transitions for Fast Pair 2, ie a pairing key is
- * included in the request (note: timeouts and retries are governed by flags, may change):
- *
- *
- * {@code
- * Connect GATT
- * A) Success -> Handshake
- * B) Failure (3s timeout) -> Retry 2x -> end
- *
- * Handshake
- * A) Generate a shared secret with the headset (either using anti-spoofing key or account key)
- * 1) Account key is used directly as the key
- * 2) Anti-spoofing key is used by combining out private key with the headset's public and
- * sending our public to the headset to combine with their private to generate a shared
- * key. Sending our public key to headset takes ~3s.
- * B) Write an encrypted packet to the headset containing their BLE address for verification
- * that both sides have the same key (headset decodes this packet and checks it against their
- * own address) (~250ms).
- * C) Receive a response from the headset containing their public address (~250ms).
- *
- * Discovery (for devices < Oreo)
- * A) Success -> Create Bond
- * B) Failure (10s timeout) -> Sleep 1s, Retry 3x -> end
- *
- * Connect to device
- * A) If already bonded
- * 1) Attempt directly connecting to supported profiles (A2DP, etc)
- * a) Success -> Write Account Key
- * b) Failure (15s timeout, usually fails within a ~2s) -> Remove bond (~1s) -> Create bond
- * B) If not already bonded
- * 1) Create bond
- * a) Success -> Connect profile
- * b) Failure (15s timeout) -> Retry 2x -> end
- * 2) Connect profile
- * a) Success -> Write account key
- * b) Failure -> Retry -> end
- *
- * Write account key
- * A) Callback that pairing succeeded
- * B) Disconnect GATT
- * C) Reconnect GATT for secure connection
- * D) Write account key (~3s)
- * }
- *
- *
- * The performance profiling result by {@link TimingLogger}:
- *
- *
- */
-// TODO(b/203441105): break down FastPairDualConnection into smaller classes.
-public class FastPairDualConnection extends FastPairConnection {
-
- private static final String TAG = FastPairDualConnection.class.getSimpleName();
-
- @VisibleForTesting
- static final int GATT_ERROR_CODE_FAST_PAIR_SIGNAL_LOST = 10000;
- @VisibleForTesting
- static final int GATT_ERROR_CODE_FAST_PAIR_ADDRESS_ROTATED = 20000;
- @VisibleForTesting
- static final int GATT_ERROR_CODE_USER_RETRY = 30000;
- @VisibleForTesting
- static final int GATT_ERROR_CODE_PAIR_WITH_SAME_MODEL_ID_COUNT = 40000;
- @VisibleForTesting
- static final int GATT_ERROR_CODE_TIMEOUT = 1000;
-
- @Nullable
- private static String sInitialConnectionFirmwareVersion;
- private static final byte[] REQUESTED_SERVICES_LTV =
- new Ltv(
- TransportDiscoveryService.SERVICE_UUIDS_16_BIT_LIST_TYPE,
- toBytes(
- ByteOrder.LITTLE_ENDIAN,
- Constants.A2DP_SINK_SERVICE_UUID,
- Constants.HANDS_FREE_SERVICE_UUID,
- Constants.HEADSET_SERVICE_UUID))
- .getBytes();
- private static final byte[] TDS_CONTROL_POINT_REQUEST =
- concat(
- new byte[]{
- TransportDiscoveryService.ControlPointCharacteristic
- .ACTIVATE_TRANSPORT_OP_CODE,
- TransportDiscoveryService.BLUETOOTH_SIG_ORGANIZATION_ID
- },
- REQUESTED_SERVICES_LTV);
-
- private static boolean sTestMode = false;
-
- static void enableTestMode() {
- sTestMode = true;
- }
-
- /**
- * Operation Result Code.
- */
- @Retention(RetentionPolicy.SOURCE)
- @IntDef(
- value = {
- ResultCode.UNKNOWN,
- ResultCode.SUCCESS,
- ResultCode.OP_CODE_NOT_SUPPORTED,
- ResultCode.INVALID_PARAMETER,
- ResultCode.UNSUPPORTED_ORGANIZATION_ID,
- ResultCode.OPERATION_FAILED,
- })
-
- public @interface ResultCode {
-
- int UNKNOWN = (byte) 0xFF;
- int SUCCESS = (byte) 0x00;
- int OP_CODE_NOT_SUPPORTED = (byte) 0x01;
- int INVALID_PARAMETER = (byte) 0x02;
- int UNSUPPORTED_ORGANIZATION_ID = (byte) 0x03;
- int OPERATION_FAILED = (byte) 0x04;
- }
-
-
- private static @ResultCode int fromTdsControlPointIndication(byte[] response) {
- return response == null || response.length < 2 ? ResultCode.UNKNOWN : from(response[1]);
- }
-
- private static @ResultCode int from(byte byteValue) {
- switch (byteValue) {
- case ResultCode.UNKNOWN:
- case ResultCode.SUCCESS:
- case ResultCode.OP_CODE_NOT_SUPPORTED:
- case ResultCode.INVALID_PARAMETER:
- case ResultCode.UNSUPPORTED_ORGANIZATION_ID:
- case ResultCode.OPERATION_FAILED:
- return byteValue;
- default:
- return ResultCode.UNKNOWN;
- }
- }
-
- private static class BrEdrHandoverInformation {
-
- private final byte[] mBluetoothAddress;
- private final short[] mProfiles;
-
- private BrEdrHandoverInformation(byte[] bluetoothAddress, short[] profiles) {
- this.mBluetoothAddress = bluetoothAddress;
-
- // For now, since we only connect to one profile, prefer A2DP Sink over headset/HFP.
- // TODO(b/37167120): Connect to more than one profile.
- Set profileSet = new HashSet<>(Shorts.asList(profiles));
- if (profileSet.contains(Constants.A2DP_SINK_SERVICE_UUID)) {
- profileSet.remove(Constants.HEADSET_SERVICE_UUID);
- profileSet.remove(Constants.HANDS_FREE_SERVICE_UUID);
- }
- this.mProfiles = Shorts.toArray(profileSet);
- }
-
- @Override
- public String toString() {
- return "BrEdrHandoverInformation{"
- + maskBluetoothAddress(BluetoothAddress.encode(mBluetoothAddress))
- + ", profiles="
- + (mProfiles.length > 0 ? Shorts.join(",", mProfiles) : "(none)")
- + "}";
- }
- }
-
- private final Context mContext;
- private final Preferences mPreferences;
- private final EventLoggerWrapper mEventLogger;
- private final BluetoothAdapter mBluetoothAdapter =
- checkNotNull(BluetoothAdapter.getDefaultAdapter());
- private String mBleAddress;
-
- private final TimingLogger mTimingLogger;
- private GattConnectionManager mGattConnectionManager;
- private boolean mProviderInitiatesBonding;
- private @Nullable
- byte[] mPairingSecret;
- private @Nullable
- byte[] mPairingKey;
- @Nullable
- private String mPublicAddress;
- @VisibleForTesting
- @Nullable
- FastPairHistoryFinder mPairedHistoryFinder;
- @Nullable
- private String mProviderDeviceName = null;
- private boolean mNeedUpdateProviderName = false;
- @Nullable
- DeviceNameReceiver mDeviceNameReceiver;
- @Nullable
- private HandshakeHandler mHandshakeHandlerForTest;
- @Nullable
- private Runnable mBeforeDirectlyConnectProfileFromCacheForTest;
-
- public FastPairDualConnection(
- Context context,
- String bleAddress,
- Preferences preferences,
- @Nullable EventLogger eventLogger) {
- this(context, bleAddress, preferences, eventLogger,
- new TimingLogger("FastPairDualConnection", preferences));
- }
-
- @VisibleForTesting
- FastPairDualConnection(
- Context context,
- String bleAddress,
- Preferences preferences,
- @Nullable EventLogger eventLogger,
- TimingLogger timingLogger) {
- this.mContext = context;
- this.mPreferences = preferences;
- this.mEventLogger = new EventLoggerWrapper(eventLogger);
- this.mBleAddress = bleAddress;
- this.mTimingLogger = timingLogger;
- }
-
- /**
- * Unpairs with headphones. Synchronous: Blocks until unpaired. Throws on any error.
- */
- @WorkerThread
- public void unpair(BluetoothDevice device)
- throws ReflectionException, InterruptedException, ExecutionException, TimeoutException,
- PairingException {
- if (mPreferences.getExtraLoggingInformation() != null) {
- mEventLogger
- .bind(mContext, device.getAddress(), mPreferences.getExtraLoggingInformation());
- }
- new BluetoothAudioPairer(
- mContext,
- device,
- mPreferences,
- mEventLogger,
- /* keyBasedPairingInfo= */ null,
- /* passkeyConfirmationHandler= */ null,
- mTimingLogger)
- .unpair();
- if (mEventLogger.isBound()) {
- mEventLogger.unbind(mContext);
- }
- }
-
- /**
- * Sets the fast pair history for identifying the provider which has paired (without being
- * forgotten) with the primary account on the device, i.e. the history is not limited on this
- * phone, can be on other phones with the same account. If they have already paired, Fast Pair
- * should not generate new account key and default personalized name for it after initial pair.
- */
- @WorkerThread
- public void setFastPairHistory(List fastPairHistoryItem) {
- Log.i(TAG, "Paired history has been set.");
- this.mPairedHistoryFinder = new FastPairHistoryFinder(fastPairHistoryItem);
- }
-
- /**
- * Update the provider device name when we take provider default name and account based name
- * into consideration.
- */
- public void setProviderDeviceName(String deviceName) {
- Log.i(TAG, "Update provider device name = " + deviceName);
- mProviderDeviceName = deviceName;
- mNeedUpdateProviderName = true;
- }
-
- /**
- * Gets the device name from the Provider (via GATT notify).
- */
- @Nullable
- public String getProviderDeviceName() {
- if (mDeviceNameReceiver == null) {
- Log.i(TAG, "getProviderDeviceName failed, deviceNameReceiver == null.");
- return null;
- }
- if (mPairingSecret == null) {
- Log.i(TAG, "getProviderDeviceName failed, pairingSecret == null.");
- return null;
- }
- String deviceName = mDeviceNameReceiver.getParsedResult(mPairingSecret);
- Log.i(TAG, "getProviderDeviceName = " + deviceName);
-
- return deviceName;
- }
-
- /**
- * Get the existing account key of the provider, this API can be called after handshake.
- *
- * @return the existing account key if the provider has paired with the account before.
- * Otherwise, return null, i.e. it is a real initial pairing.
- */
- @WorkerThread
- @Nullable
- public byte[] getExistingAccountKey() {
- return mPairedHistoryFinder == null ? null : mPairedHistoryFinder.getExistingAccountKey();
- }
-
- /**
- * Pairs with headphones. Synchronous: Blocks until paired and connected. Throws on any error.
- *
- * @return the secret key for the user's account, if written.
- */
- @WorkerThread
- @Nullable
- public SharedSecret pair()
- throws BluetoothException, InterruptedException, ReflectionException, TimeoutException,
- ExecutionException, PairingException {
- try {
- return pair(/*key=*/ null);
- } catch (GeneralSecurityException e) {
- throw new RuntimeException("Should never happen, no security key!", e);
- }
- }
-
- /**
- * Pairs with headphones. Synchronous: Blocks until paired and connected. Throws on any error.
- *
- * @param key can be in two different formats. If it is 16 bytes long, then it is an AES account
- * key. Otherwise, it's a public key generated by {@link EllipticCurveDiffieHellmanExchange}.
- * See go/fast-pair-2-spec for how each of these keys are used.
- * @return the secret key for the user's account, if written
- */
- @WorkerThread
- @Nullable
- public SharedSecret pair(@Nullable byte[] key)
- throws BluetoothException, InterruptedException, ReflectionException, TimeoutException,
- ExecutionException, PairingException, GeneralSecurityException {
- mPairingKey = key;
- if (key != null) {
- Log.i(TAG, "Starting to pair " + maskBluetoothAddress(mBleAddress) + ": key["
- + key.length + "], " + mPreferences);
- } else {
- Log.i(TAG, "Pairing " + maskBluetoothAddress(mBleAddress) + ": " + mPreferences);
- }
- if (mPreferences.getExtraLoggingInformation() != null) {
- this.mEventLogger.bind(
- mContext, mBleAddress, mPreferences.getExtraLoggingInformation());
- }
- // Provider never initiates if key is null (Fast Pair 1.0).
- if (key != null && mPreferences.getProviderInitiatesBondingIfSupported()) {
- // Provider can't initiate if we can't get our own public address, so check.
- this.mEventLogger.setCurrentEvent(EventCode.GET_LOCAL_PUBLIC_ADDRESS);
- if (BluetoothAddress.getPublicAddress(mContext) != null) {
- this.mEventLogger.logCurrentEventSucceeded();
- mProviderInitiatesBonding = true;
- } else {
- this.mEventLogger
- .logCurrentEventFailed(new IllegalStateException("null bluetooth_address"));
- Log.e(TAG,
- "Want provider to initiate bonding, but cannot access Bluetooth public "
- + "address. Falling back to initiating bonding ourselves.");
- }
- }
-
- // User might be pairing with a bonded device. In this case, we just connect profile
- // directly and finish pairing.
- if (directConnectProfileWithCachedAddress()) {
- callbackOnPaired();
- mTimingLogger.dump();
- if (mEventLogger.isBound()) {
- mEventLogger.unbind(mContext);
- }
- return null;
- }
-
- // Lazily initialize a new connection manager for each pairing request.
- initGattConnectionManager();
- boolean isSecretHandshakeCompleted = true;
-
- try {
- if (key != null && key.length > 0) {
- // GATT_CONNECTION_AND_SECRET_HANDSHAKE start.
- mEventLogger.setCurrentEvent(EventCode.GATT_CONNECTION_AND_SECRET_HANDSHAKE);
- isSecretHandshakeCompleted = false;
- Exception lastException = null;
- boolean lastExceptionFromHandshake = false;
- long startTime = SystemClock.elapsedRealtime();
- // We communicate over this connection twice for Key-based Pairing: once before
- // bonding begins, and once during (to transfer the passkey). Empirically, keeping
- // it alive throughout is far more reliable than disconnecting and reconnecting for
- // each step. The while loop is for retry of GATT connection and handshake only.
- do {
- boolean isHandshaking = false;
- try (BluetoothGattConnection connection =
- mGattConnectionManager
- .getConnectionWithSignalLostCheck(mRescueFromError)) {
- mEventLogger.setCurrentEvent(EventCode.SECRET_HANDSHAKE);
- if (lastException != null && !lastExceptionFromHandshake) {
- logRetrySuccessEvent(EventCode.RECOVER_BY_RETRY_GATT, lastException,
- mEventLogger);
- lastException = null;
- }
- try (ScopedTiming scopedTiming = new ScopedTiming(mTimingLogger,
- "Handshake")) {
- isHandshaking = true;
- handshakeForKeyBasedPairing(key);
- // After handshake, Fast Pair has the public address of the provider, so
- // we can check if it has paired with the account.
- if (mPublicAddress != null && mPairedHistoryFinder != null) {
- if (mPairedHistoryFinder.isInPairedHistory(mPublicAddress)) {
- Log.i(TAG, "The provider is found in paired history.");
- } else {
- Log.i(TAG, "The provider is not found in paired history.");
- }
- }
- }
- isHandshaking = false;
- // SECRET_HANDSHAKE end.
- mEventLogger.logCurrentEventSucceeded();
- isSecretHandshakeCompleted = true;
- if (mPrepareCreateBondCallback != null) {
- mPrepareCreateBondCallback.run();
- }
- if (lastException != null && lastExceptionFromHandshake) {
- logRetrySuccessEvent(EventCode.RECOVER_BY_RETRY_HANDSHAKE_RECONNECT,
- lastException, mEventLogger);
- }
- logManualRetryCounts(/* success= */ true);
- // GATT_CONNECTION_AND_SECRET_HANDSHAKE end.
- mEventLogger.logCurrentEventSucceeded();
- return pair(mPreferences.getEnableBrEdrHandover());
- } catch (SignalLostException e) {
- long spentTime = SystemClock.elapsedRealtime() - startTime;
- if (spentTime > mPreferences.getAddressRotateRetryMaxSpentTimeMs()) {
- Log.w(TAG, "Signal lost but already spend too much time " + spentTime
- + "ms");
- throw e;
- }
-
- logCurrentEventFailedBySignalLost(e);
- lastException = (Exception) e.getCause();
- lastExceptionFromHandshake = isHandshaking;
- if (mRescueFromError != null && isHandshaking) {
- mRescueFromError.accept(ErrorCode.SUCCESS_SECRET_HANDSHAKE_RECONNECT);
- }
- Log.i(TAG, "Signal lost, retry");
- // In case we meet some GATT error which is not recoverable and fail very
- // quick.
- SystemClock.sleep(mPreferences.getPairingRetryDelayMs());
- } catch (SignalRotatedException e) {
- long spentTime = SystemClock.elapsedRealtime() - startTime;
- if (spentTime > mPreferences.getAddressRotateRetryMaxSpentTimeMs()) {
- Log.w(TAG, "Address rotated but already spend too much time "
- + spentTime + "ms");
- throw e;
- }
-
- logCurrentEventFailedBySignalRotated(e);
- setBleAddress(e.getNewAddress());
- lastException = (Exception) e.getCause();
- lastExceptionFromHandshake = isHandshaking;
- if (mRescueFromError != null) {
- mRescueFromError.accept(ErrorCode.SUCCESS_ADDRESS_ROTATE);
- }
- Log.i(TAG, "Address rotated, retry");
- } catch (HandshakeException e) {
- long spentTime = SystemClock.elapsedRealtime() - startTime;
- if (spentTime > mPreferences
- .getSecretHandshakeRetryGattConnectionMaxSpentTimeMs()) {
- Log.w(TAG, "Secret handshake failed but already spend too much time "
- + spentTime + "ms");
- throw e.getOriginalException();
- }
- if (mEventLogger.isCurrentEvent()) {
- mEventLogger.logCurrentEventFailed(e.getOriginalException());
- }
- initGattConnectionManager();
- lastException = e.getOriginalException();
- lastExceptionFromHandshake = true;
- if (mRescueFromError != null) {
- mRescueFromError.accept(ErrorCode.SUCCESS_SECRET_HANDSHAKE_RECONNECT);
- }
- Log.i(TAG, "Handshake failed, retry GATT connection");
- }
- } while (mPreferences.getRetryGattConnectionAndSecretHandshake());
- }
- if (mPrepareCreateBondCallback != null) {
- mPrepareCreateBondCallback.run();
- }
- return pair(mPreferences.getEnableBrEdrHandover());
- } catch (SignalLostException e) {
- logCurrentEventFailedBySignalLost(e);
- // GATT_CONNECTION_AND_SECRET_HANDSHAKE end.
- if (!isSecretHandshakeCompleted) {
- logManualRetryCounts(/* success= */ false);
- logCurrentEventFailedBySignalLost(e);
- }
- throw e;
- } catch (SignalRotatedException e) {
- logCurrentEventFailedBySignalRotated(e);
- // GATT_CONNECTION_AND_SECRET_HANDSHAKE end.
- if (!isSecretHandshakeCompleted) {
- logManualRetryCounts(/* success= */ false);
- logCurrentEventFailedBySignalRotated(e);
- }
- throw e;
- } catch (BluetoothException
- | InterruptedException
- | ReflectionException
- | TimeoutException
- | ExecutionException
- | PairingException
- | GeneralSecurityException e) {
- if (mEventLogger.isCurrentEvent()) {
- mEventLogger.logCurrentEventFailed(e);
- }
- // GATT_CONNECTION_AND_SECRET_HANDSHAKE end.
- if (!isSecretHandshakeCompleted) {
- logManualRetryCounts(/* success= */ false);
- if (mEventLogger.isCurrentEvent()) {
- mEventLogger.logCurrentEventFailed(e);
- }
- }
- throw e;
- } finally {
- mTimingLogger.dump();
- if (mEventLogger.isBound()) {
- mEventLogger.unbind(mContext);
- }
- }
- }
-
- private boolean directConnectProfileWithCachedAddress() throws ReflectionException {
- if (TextUtils.isEmpty(mPreferences.getCachedDeviceAddress())
- || !mPreferences.getDirectConnectProfileIfModelIdInCache()
- || mPreferences.getSkipConnectingProfiles()) {
- return false;
- }
- Log.i(TAG, "Try to direct connect profile with cached address "
- + maskBluetoothAddress(mPreferences.getCachedDeviceAddress()));
- mEventLogger.setCurrentEvent(EventCode.DIRECTLY_CONNECT_PROFILE_WITH_CACHED_ADDRESS);
- BluetoothDevice device =
- mBluetoothAdapter.getRemoteDevice(mPreferences.getCachedDeviceAddress()).unwrap();
- AtomicBoolean interruptConnection = new AtomicBoolean(false);
- BroadcastReceiver receiver =
- new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- if (intent == null
- || !BluetoothDevice.ACTION_PAIRING_REQUEST
- .equals(intent.getAction())) {
- return;
- }
- BluetoothDevice pairingDevice = intent
- .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
- if (pairingDevice == null || !device.getAddress()
- .equals(pairingDevice.getAddress())) {
- return;
- }
- abortBroadcast();
- // Should be the clear link key case, make it fail directly to go back to
- // initial pairing process.
- pairingDevice.setPairingConfirmation(/* confirm= */ false);
- Log.w(TAG, "Get pairing request broadcast for device "
- + maskBluetoothAddress(device.getAddress())
- + " while try to direct connect profile with cached address, reject"
- + " and to go back to initial pairing process");
- interruptConnection.set(true);
- }
- };
- mContext.registerReceiver(receiver,
- new IntentFilter(BluetoothDevice.ACTION_PAIRING_REQUEST));
- try (ScopedTiming scopedTiming =
- new ScopedTiming(mTimingLogger,
- "Connect to profile with cached address directly")) {
- if (mBeforeDirectlyConnectProfileFromCacheForTest != null) {
- mBeforeDirectlyConnectProfileFromCacheForTest.run();
- }
- attemptConnectProfiles(
- new BluetoothAudioPairer(
- mContext,
- device,
- mPreferences,
- mEventLogger,
- /* keyBasedPairingInfo= */ null,
- /* passkeyConfirmationHandler= */ null,
- mTimingLogger),
- maskBluetoothAddress(device),
- getSupportedProfiles(device),
- /* numConnectionAttempts= */ 1,
- /* enablePairingBehavior= */ false,
- interruptConnection);
- Log.i(TAG,
- "Directly connected to " + maskBluetoothAddress(device)
- + "with cached address.");
- mEventLogger.logCurrentEventSucceeded();
- mEventLogger.setDevice(device);
- logPairWithPossibleCachedAddress(device.getAddress());
- return true;
- } catch (PairingException e) {
- if (interruptConnection.get()) {
- Log.w(TAG, "Fail to connected to " + maskBluetoothAddress(device)
- + " with cached address due to link key is cleared.", e);
- mEventLogger.logCurrentEventFailed(
- new ConnectException(ConnectErrorCode.LINK_KEY_CLEARED,
- "Link key is cleared"));
- } else {
- Log.w(TAG, "Fail to connected to " + maskBluetoothAddress(device)
- + " with cached address.", e);
- mEventLogger.logCurrentEventFailed(e);
- }
- return false;
- } finally {
- mContext.unregisterReceiver(receiver);
- }
- }
-
- /**
- * Logs for user retry, check go/fastpairquality21q3 for more details.
- */
- private void logManualRetryCounts(boolean success) {
- if (!mPreferences.getLogUserManualRetry()) {
- return;
- }
-
- // We don't want to be the final event on analytics.
- if (!mEventLogger.isCurrentEvent()) {
- return;
- }
-
- mEventLogger.setCurrentEvent(EventCode.GATT_HANDSHAKE_MANUAL_RETRY_ATTEMPTS);
- if (mPreferences.getPairFailureCounts() <= 0 && success) {
- mEventLogger.logCurrentEventSucceeded();
- } else {
- int errorCode = mPreferences.getPairFailureCounts();
- if (errorCode > 99) {
- errorCode = 99;
- }
- errorCode += success ? 0 : 100;
- // To not conflict with current error codes.
- errorCode += GATT_ERROR_CODE_USER_RETRY;
- mEventLogger.logCurrentEventFailed(
- new BluetoothGattException("Error for manual retry", errorCode));
- }
- }
-
- static void logRetrySuccessEvent(
- @EventCode int eventCode,
- @Nullable Exception recoverFromException,
- EventLoggerWrapper eventLogger) {
- if (recoverFromException == null) {
- return;
- }
- eventLogger.setCurrentEvent(eventCode);
- eventLogger.logCurrentEventFailed(recoverFromException);
- }
-
- private void initGattConnectionManager() {
- mGattConnectionManager =
- new GattConnectionManager(
- mContext,
- mPreferences,
- mEventLogger,
- mBluetoothAdapter,
- this::toggleBluetooth,
- mBleAddress,
- mTimingLogger,
- mFastPairSignalChecker,
- isPairingWithAntiSpoofingPublicKey());
- }
-
- private void logCurrentEventFailedBySignalRotated(SignalRotatedException e) {
- if (!mEventLogger.isCurrentEvent()) {
- return;
- }
-
- Log.w(TAG, "BLE Address for pairing device might rotated!");
- mEventLogger.logCurrentEventFailed(
- new BluetoothGattException(
- "BLE Address for pairing device might rotated",
- appendMoreErrorCode(GATT_ERROR_CODE_FAST_PAIR_ADDRESS_ROTATED,
- e.getCause()),
- e));
- }
-
- private void logCurrentEventFailedBySignalLost(SignalLostException e) {
- if (!mEventLogger.isCurrentEvent()) {
- return;
- }
-
- Log.w(TAG, "BLE signal for pairing device might lost!");
- mEventLogger.logCurrentEventFailed(
- new BluetoothGattException(
- "BLE signal for pairing device might lost",
- appendMoreErrorCode(GATT_ERROR_CODE_FAST_PAIR_SIGNAL_LOST, e.getCause()),
- e));
- }
-
- @VisibleForTesting
- static int appendMoreErrorCode(int masterErrorCode, @Nullable Throwable cause) {
- if (cause instanceof BluetoothGattException) {
- return masterErrorCode + ((BluetoothGattException) cause).getGattErrorCode();
- } else if (cause instanceof TimeoutException
- || cause instanceof BluetoothTimeoutException
- || cause instanceof BluetoothOperationTimeoutException) {
- return masterErrorCode + GATT_ERROR_CODE_TIMEOUT;
- } else {
- return masterErrorCode;
- }
- }
-
- private void setBleAddress(String newAddress) {
- if (TextUtils.isEmpty(newAddress) || Ascii.equalsIgnoreCase(newAddress, mBleAddress)) {
- return;
- }
-
- mBleAddress = newAddress;
-
- // Recreates a GattConnectionManager with the new address for establishing a new GATT
- // connection later.
- initGattConnectionManager();
-
- mEventLogger.setDevice(mBluetoothAdapter.getRemoteDevice(mBleAddress).unwrap());
- }
-
- /**
- * Gets the public address of the headset used in the connection. Before the handshake, this
- * could be null.
- */
- @Nullable
- public String getPublicAddress() {
- return mPublicAddress;
- }
-
- /**
- * Pairs with a Bluetooth device. In general, this process goes through the following steps:
- *
- *
- *
Get BrEdr handover information if requested
- *
Discover the device (on Android N and lower to work around a bug)
- *
Connect to the device
- *
- *
Attempt a direct connection to a supported profile if we're already bonded
- *
Create a new bond with the not bonded device and then connect to a supported
- * profile
- *
- *
Write the account secret
- *
- *
- *
Blocks until paired. May take 10+ seconds, so run on a background thread.
- */
- @Nullable
- private SharedSecret pair(boolean enableBrEdrHandover)
- throws BluetoothException, InterruptedException, ReflectionException, TimeoutException,
- ExecutionException, PairingException, GeneralSecurityException {
- BrEdrHandoverInformation brEdrHandoverInformation = null;
- if (enableBrEdrHandover) {
- try (ScopedTiming scopedTiming =
- new ScopedTiming(mTimingLogger, "Get BR/EDR handover information via GATT")) {
- brEdrHandoverInformation =
- getBrEdrHandoverInformation(mGattConnectionManager.getConnection());
- } catch (BluetoothException | TdsException e) {
- Log.w(TAG,
- "Couldn't get BR/EDR Handover info via TDS. Trying direct connect.", e);
- mEventLogger.logCurrentEventFailed(e);
- }
- }
-
- if (brEdrHandoverInformation == null) {
- // Pair directly to the BLE address. Works if the BLE and Bluetooth Classic addresses
- // are the same, or if we can do BLE cross-key transport.
- brEdrHandoverInformation =
- new BrEdrHandoverInformation(
- BluetoothAddress
- .decode(mPublicAddress != null ? mPublicAddress : mBleAddress),
- attemptGetBluetoothClassicProfiles(
- mBluetoothAdapter.getRemoteDevice(mBleAddress).unwrap(),
- mPreferences.getNumSdpAttempts()));
- }
-
- BluetoothDevice device =
- mBluetoothAdapter.getRemoteDevice(brEdrHandoverInformation.mBluetoothAddress)
- .unwrap();
- callbackOnGetAddress(device.getAddress());
- mEventLogger.setDevice(device);
-
- Log.i(TAG, "Pairing with " + brEdrHandoverInformation);
- KeyBasedPairingInfo keyBasedPairingInfo =
- mPairingSecret == null
- ? null
- : new KeyBasedPairingInfo(
- mPairingSecret, mGattConnectionManager, mProviderInitiatesBonding);
-
- BluetoothAudioPairer pairer =
- new BluetoothAudioPairer(
- mContext,
- device,
- mPreferences,
- mEventLogger,
- keyBasedPairingInfo,
- mPasskeyConfirmationHandler,
- mTimingLogger);
-
- logPairWithPossibleCachedAddress(device.getAddress());
- logPairWithModelIdInCacheAndDiscoveryFailForCachedAddress(device);
-
- // In the case where we are already bonded, we should first just try connecting to supported
- // profiles. If successful, then this will be much faster than recreating the bond like we
- // normally do and we can finish early. It is also more reliable than tearing down the bond
- // and recreating it.
- try {
- if (!sTestMode) {
- attemptDirectConnectionIfBonded(device, pairer);
- }
- callbackOnPaired();
- return maybeWriteAccountKey(device);
- } catch (PairingException e) {
- Log.i(TAG, "Failed to directly connect to supported profiles: " + e.getMessage());
- // Catches exception when we fail to connect support profile. And makes the flow to go
- // through step to write account key when device is bonded.
- if (mPreferences.getEnablePairFlowShowUiWithoutProfileConnection()
- && device.getBondState() == BluetoothDevice.BOND_BONDED) {
- if (mPreferences.getSkipConnectingProfiles()
- && !mPreferences.getCheckBondStateWhenSkipConnectingProfiles()) {
- Log.i(TAG, "For notCheckBondStateWhenSkipConnectingProfiles case should do "
- + "re-bond");
- } else {
- Log.i(TAG, "Fail to connect profile when device is bonded, still call back on"
- + "pair callback to show ui");
- callbackOnPaired();
- return maybeWriteAccountKey(device);
- }
- }
- }
-
- if (mPreferences.getMoreEventLogForQuality()) {
- switch (device.getBondState()) {
- case BOND_BONDED:
- mEventLogger.setCurrentEvent(EventCode.BEFORE_CREATE_BOND_BONDED);
- break;
- case BOND_BONDING:
- mEventLogger.setCurrentEvent(EventCode.BEFORE_CREATE_BOND_BONDING);
- break;
- case BOND_NONE:
- default:
- mEventLogger.setCurrentEvent(EventCode.BEFORE_CREATE_BOND);
- }
- }
-
- for (int i = 1; i <= mPreferences.getNumCreateBondAttempts(); i++) {
- try (ScopedTiming scopedTiming = new ScopedTiming(mTimingLogger, "Pair device #" + i)) {
- pairer.pair();
- if (mPreferences.getMoreEventLogForQuality()) {
- // For EventCode.BEFORE_CREATE_BOND
- mEventLogger.logCurrentEventSucceeded();
- }
- break;
- } catch (Exception e) {
- mEventLogger.logCurrentEventFailed(e);
- if (mPasskeyIsGotten) {
- Log.w(TAG,
- "createBond() failed because of " + e.getMessage()
- + " after getting the passkey. Skip retry.");
- if (mPreferences.getMoreEventLogForQuality()) {
- // For EventCode.BEFORE_CREATE_BOND
- mEventLogger.logCurrentEventFailed(
- new CreateBondException(
- CreateBondErrorCode.FAILED_BUT_ALREADY_RECEIVE_PASS_KEY,
- 0,
- "Already get the passkey"));
- }
- break;
- }
- Log.e(TAG,
- "removeBond() or createBond() failed, attempt " + i + " of " + mPreferences
- .getNumCreateBondAttempts() + ". Bond state "
- + device.getBondState(), e);
- if (i < mPreferences.getNumCreateBondAttempts()) {
- toggleBluetooth();
-
- // We've seen 3 createBond() failures within 100ms (!). And then success again
- // later (even without turning on/off bluetooth). So create some minimum break
- // time.
- Log.i(TAG, "Sleeping 1 sec after createBond() failure.");
- SystemClock.sleep(1000);
- } else if (mPreferences.getMoreEventLogForQuality()) {
- // For EventCode.BEFORE_CREATE_BOND
- mEventLogger.logCurrentEventFailed(e);
- }
- }
- }
- boolean deviceCreateBondFailWithNullSecret = false;
- if (!pairer.isPaired()) {
- if (mPairingSecret != null) {
- // Bonding could fail for a few different reasons here. It could be an error, an
- // attacker may have tried to bond, or the device may not be up to spec.
- throw new PairingException("createBond() failed, exiting connection process.");
- } else if (mPreferences.getSkipConnectingProfiles()) {
- throw new PairingException(
- "createBond() failed and skipping connecting to a profile.");
- } else {
- // When bond creation has failed, connecting a profile will still work most of the
- // time for Fast Pair 1.0 devices (ie, pairing secret is null), so continue on with
- // the spec anyways and attempt to connect supported profiles.
- Log.w(TAG, "createBond() failed, will try connecting profiles anyway.");
- deviceCreateBondFailWithNullSecret = true;
- }
- } else if (mPreferences.getEnablePairFlowShowUiWithoutProfileConnection()) {
- Log.i(TAG, "new flow to call on paired callback for ui when pairing step is finished");
- callbackOnPaired();
- }
-
- if (!mPreferences.getSkipConnectingProfiles()) {
- if (mPreferences.getWaitForUuidsAfterBonding()
- && brEdrHandoverInformation.mProfiles.length == 0) {
- short[] supportedProfiles = getCachedUuids(device);
- if (supportedProfiles.length == 0
- && mPreferences.getNumSdpAttemptsAfterBonded() > 0) {
- Log.i(TAG, "Found no supported profiles in UUID cache, manually trigger SDP.");
- attemptGetBluetoothClassicProfiles(device,
- mPreferences.getNumSdpAttemptsAfterBonded());
- }
- brEdrHandoverInformation =
- new BrEdrHandoverInformation(
- brEdrHandoverInformation.mBluetoothAddress, supportedProfiles);
- }
- short[] profiles = brEdrHandoverInformation.mProfiles;
- if (profiles.length == 0) {
- profiles = Constants.getSupportedProfiles();
- Log.w(TAG,
- "Attempting to connect constants profiles, " + Arrays.toString(profiles));
- } else {
- Log.i(TAG, "Attempting to connect device profiles, " + Arrays.toString(profiles));
- }
-
- try {
- attemptConnectProfiles(
- pairer,
- maskBluetoothAddress(device),
- profiles,
- mPreferences.getNumConnectAttempts(),
- /* enablePairingBehavior= */ false);
- } catch (PairingException e) {
- // For new pair flow to show ui, we already show success ui when finishing the
- // createBond step. So we should catch the exception from connecting profile to
- // avoid showing fail ui for user.
- if (mPreferences.getEnablePairFlowShowUiWithoutProfileConnection()
- && !deviceCreateBondFailWithNullSecret) {
- Log.i(TAG, "Fail to connect profile when device is bonded");
- } else {
- throw e;
- }
- }
- }
- if (!mPreferences.getEnablePairFlowShowUiWithoutProfileConnection()) {
- Log.i(TAG, "original flow to call on paired callback for ui");
- callbackOnPaired();
- } else if (deviceCreateBondFailWithNullSecret) {
- // This paired callback is called for device which create bond fail with null secret
- // such as FastPair 1.0 device when directly connecting to any supported profile.
- Log.i(TAG, "call on paired callback for ui for device with null secret without bonded "
- + "state");
- callbackOnPaired();
- }
- if (mPreferences.getEnableFirmwareVersionCharacteristic()
- && validateBluetoothGattCharacteristic(
- mGattConnectionManager.getConnection(), FirmwareVersionCharacteristic.ID)) {
- try {
- sInitialConnectionFirmwareVersion = readFirmwareVersion();
- } catch (BluetoothException e) {
- Log.i(TAG, "Fast Pair: head phone does not support firmware read", e);
- }
- }
-
- // Catch exception when writing account key or name fail to avoid showing pairing failure
- // notice for user. Because device is already paired successfully based on paring step.
- SharedSecret secret = null;
- try {
- secret = maybeWriteAccountKey(device);
- } catch (InterruptedException
- | ExecutionException
- | TimeoutException
- | NoSuchAlgorithmException
- | BluetoothException e) {
- Log.w(TAG, "Fast Pair: Got exception when writing account key or name to provider", e);
- }
-
- return secret;
- }
-
- private void logPairWithPossibleCachedAddress(String brEdrAddressForBonding) {
- if (TextUtils.isEmpty(mPreferences.getPossibleCachedDeviceAddress())
- || !mPreferences.getLogPairWithCachedModelId()) {
- return;
- }
- mEventLogger.setCurrentEvent(EventCode.PAIR_WITH_CACHED_MODEL_ID);
- if (Ascii.equalsIgnoreCase(
- mPreferences.getPossibleCachedDeviceAddress(), brEdrAddressForBonding)) {
- mEventLogger.logCurrentEventSucceeded();
- Log.i(TAG, "Repair with possible cached device "
- + maskBluetoothAddress(mPreferences.getPossibleCachedDeviceAddress()));
- } else {
- mEventLogger.logCurrentEventFailed(
- new PairingException("Pairing with 2nd device with same model ID"));
- Log.i(TAG, "Pair with a new device " + maskBluetoothAddress(brEdrAddressForBonding)
- + " with model ID in cache "
- + maskBluetoothAddress(mPreferences.getPossibleCachedDeviceAddress()));
- }
- }
-
- /**
- * Logs two type of events. First, why cachedAddress mechanism doesn't work if it's repair with
- * bonded device case. Second, if it's not the case, log how many devices with the same model Id
- * is already paired.
- */
- private void logPairWithModelIdInCacheAndDiscoveryFailForCachedAddress(BluetoothDevice device) {
- if (!mPreferences.getLogPairWithCachedModelId()) {
- return;
- }
-
- if (device.getBondState() == BOND_BONDED) {
- if (mPreferences.getSameModelIdPairedDeviceCount() <= 0) {
- Log.i(TAG, "Device is bonded but we don't have this model Id in cache.");
- } else if (TextUtils.isEmpty(mPreferences.getCachedDeviceAddress())
- && mPreferences.getDirectConnectProfileIfModelIdInCache()
- && !mPreferences.getSkipConnectingProfiles()) {
- // Pair with bonded device case. Log why the cached address is not found.
- mEventLogger.setCurrentEvent(
- EventCode.DIRECTLY_CONNECT_PROFILE_WITH_CACHED_ADDRESS);
- mEventLogger.logCurrentEventFailed(
- mPreferences.getIsDeviceFinishCheckAddressFromCache()
- ? new ConnectException(ConnectErrorCode.FAIL_TO_DISCOVERY,
- "Failed to discovery")
- : new ConnectException(
- ConnectErrorCode.DISCOVERY_NOT_FINISHED,
- "Discovery not finished"));
- Log.i(TAG, "Failed to get cached address due to "
- + (mPreferences.getIsDeviceFinishCheckAddressFromCache()
- ? "Failed to discovery"
- : "Discovery not finished"));
- }
- } else if (device.getBondState() == BOND_NONE) {
- // Pair with new device case, log how many devices with the same model id is in FastPair
- // cache already.
- mEventLogger.setCurrentEvent(EventCode.PAIR_WITH_NEW_MODEL);
- if (mPreferences.getSameModelIdPairedDeviceCount() <= 0) {
- mEventLogger.logCurrentEventSucceeded();
- } else {
- mEventLogger.logCurrentEventFailed(
- new BluetoothGattException(
- "Already have this model ID in cache",
- GATT_ERROR_CODE_PAIR_WITH_SAME_MODEL_ID_COUNT
- + mPreferences.getSameModelIdPairedDeviceCount()));
- }
- Log.i(TAG, "This device already has " + mPreferences.getSameModelIdPairedDeviceCount()
- + " peripheral with the same model Id");
- }
- }
-
- /**
- * Attempts to directly connect to any supported profile if we're already bonded, this will save
- * time over tearing down the bond and recreating it.
- */
- private void attemptDirectConnectionIfBonded(BluetoothDevice device,
- BluetoothAudioPairer pairer)
- throws PairingException {
- if (mPreferences.getSkipConnectingProfiles()) {
- if (mPreferences.getCheckBondStateWhenSkipConnectingProfiles()
- && device.getBondState() == BluetoothDevice.BOND_BONDED) {
- Log.i(TAG, "Skipping connecting to profiles by preferences.");
- return;
- }
- throw new PairingException(
- "Skipping connecting to profiles, no direct connection possible.");
- } else if (!mPreferences.getAttemptDirectConnectionWhenPreviouslyBonded()
- || device.getBondState() != BluetoothDevice.BOND_BONDED) {
- throw new PairingException(
- "Not previously bonded skipping direct connection, %s", device.getBondState());
- }
- short[] supportedProfiles = getSupportedProfiles(device);
- mEventLogger.setCurrentEvent(EventCode.DIRECTLY_CONNECTED_TO_PROFILE);
- try (ScopedTiming scopedTiming =
- new ScopedTiming(mTimingLogger, "Connect to profile directly")) {
- attemptConnectProfiles(
- pairer,
- maskBluetoothAddress(device),
- supportedProfiles,
- mPreferences.getEnablePairFlowShowUiWithoutProfileConnection()
- ? mPreferences.getNumConnectAttempts()
- : 1,
- mPreferences.getEnablePairingWhileDirectlyConnecting());
- Log.i(TAG, "Directly connected to " + maskBluetoothAddress(device));
- mEventLogger.logCurrentEventSucceeded();
- } catch (PairingException e) {
- mEventLogger.logCurrentEventFailed(e);
- // Rethrow e so that the exception bubbles up and we continue the normal pairing
- // process.
- throw e;
- }
- }
-
- @VisibleForTesting
- void attemptConnectProfiles(
- BluetoothAudioPairer pairer,
- String deviceMaskedBluetoothAddress,
- short[] profiles,
- int numConnectionAttempts,
- boolean enablePairingBehavior)
- throws PairingException {
- attemptConnectProfiles(
- pairer,
- deviceMaskedBluetoothAddress,
- profiles,
- numConnectionAttempts,
- enablePairingBehavior,
- new AtomicBoolean(false));
- }
-
- private void attemptConnectProfiles(
- BluetoothAudioPairer pairer,
- String deviceMaskedBluetoothAddress,
- short[] profiles,
- int numConnectionAttempts,
- boolean enablePairingBehavior,
- AtomicBoolean interruptConnection)
- throws PairingException {
- if (mPreferences.getMoreEventLogForQuality()) {
- mEventLogger.setCurrentEvent(EventCode.BEFORE_CONNECT_PROFILE);
- }
- Exception lastException = null;
- for (short profile : profiles) {
- if (interruptConnection.get()) {
- Log.w(TAG, "attemptConnectProfiles interrupted");
- break;
- }
- if (!mPreferences.isSupportedProfile(profile)) {
- Log.w(TAG, "Ignoring unsupported profile=" + profile);
- continue;
- }
- for (int i = 1; i <= numConnectionAttempts; i++) {
- if (interruptConnection.get()) {
- Log.w(TAG, "attemptConnectProfiles interrupted");
- break;
- }
- mEventLogger.setCurrentEvent(EventCode.CONNECT_PROFILE);
- mEventLogger.setCurrentProfile(profile);
- try {
- pairer.connect(profile, enablePairingBehavior);
- mEventLogger.logCurrentEventSucceeded();
- if (mPreferences.getMoreEventLogForQuality()) {
- // For EventCode.BEFORE_CONNECT_PROFILE
- mEventLogger.logCurrentEventSucceeded();
- }
- // If successful, we're done.
- // TODO(b/37167120): Connect to more than one profile.
- return;
- } catch (InterruptedException
- | ReflectionException
- | TimeoutException
- | ExecutionException
- | ConnectException e) {
- Log.w(TAG,
- "Error connecting to profile=" + profile
- + " for device=" + deviceMaskedBluetoothAddress
- + " (attempt " + i + " of " + mPreferences
- .getNumConnectAttempts(), e);
- mEventLogger.logCurrentEventFailed(e);
- lastException = e;
- }
- }
- }
- if (mPreferences.getMoreEventLogForQuality()) {
- // For EventCode.BEFORE_CONNECT_PROFILE
- if (lastException != null) {
- mEventLogger.logCurrentEventFailed(lastException);
- } else {
- mEventLogger.logCurrentEventSucceeded();
- }
- }
- throw new PairingException(
- "Unable to connect to any profiles in: %s", Arrays.toString(profiles));
- }
-
- /**
- * Checks whether or not an account key should be written to the device and writes it if so.
- * This is called after handle notifying the pairedCallback that we've finished pairing, because
- * at this point the headset is ready to use.
- */
- @Nullable
- private SharedSecret maybeWriteAccountKey(BluetoothDevice device)
- throws InterruptedException, ExecutionException, TimeoutException,
- NoSuchAlgorithmException,
- BluetoothException {
- if (!sTestMode) {
- Locator.get(mContext, FastPairController.class).setShouldUpload(false);
- }
- if (!shouldWriteAccountKey()) {
- // For FastPair 2.0, here should be a subsequent pairing case.
- return null;
- }
-
- // Check if it should be a subsequent pairing but go through initial pairing. If there is an
- // existed paired history found, use the same account key instead of creating a new one.
- byte[] accountKey =
- mPairedHistoryFinder == null ? null : mPairedHistoryFinder.getExistingAccountKey();
- if (accountKey == null) {
- // It is a real initial pairing, generate a new account key for the headset.
- try (ScopedTiming scopedTiming1 =
- new ScopedTiming(mTimingLogger, "Write account key")) {
- accountKey = doWriteAccountKey(createAccountKey(), device.getAddress());
- if (accountKey == null) {
- // Without writing account key back to provider, close the connection.
- mGattConnectionManager.closeConnection();
- return null;
- }
- if (!mPreferences.getIsRetroactivePairing()) {
- try (ScopedTiming scopedTiming2 = new ScopedTiming(mTimingLogger,
- "Start CloudSyncing")) {
- // Start to sync to the footprint
- Locator.get(mContext, FastPairController.class).setShouldUpload(true);
- //mContext.startService(createCloudSyncingIntent(accountKey));
- } catch (SecurityException e) {
- Log.w(TAG, "Error adding device.", e);
- }
- }
- }
- } else if (shouldWriteAccountKeyForExistingCase(accountKey)) {
- // There is an existing account key, but go through initial pairing, and still write the
- // existing account key.
- doWriteAccountKey(accountKey, device.getAddress());
- }
-
- // When finish writing account key in initial pairing, write new device name back to
- // provider.
- UUID characteristicUuid = NameCharacteristic.getId(mGattConnectionManager.getConnection());
- if (mPreferences.getEnableNamingCharacteristic()
- && mNeedUpdateProviderName
- && validateBluetoothGattCharacteristic(
- mGattConnectionManager.getConnection(), characteristicUuid)) {
- try (ScopedTiming scopedTiming = new ScopedTiming(mTimingLogger,
- "WriteNameToProvider")) {
- writeNameToProvider(this.mProviderDeviceName, device.getAddress());
- }
- }
-
- // When finish writing account key and name back to provider, close the connection.
- mGattConnectionManager.closeConnection();
- return SharedSecret.create(accountKey, device.getAddress());
- }
-
- private boolean shouldWriteAccountKey() {
- return isWritingAccountKeyEnabled() && isPairingWithAntiSpoofingPublicKey();
- }
-
- private boolean isWritingAccountKeyEnabled() {
- return mPreferences.getNumWriteAccountKeyAttempts() > 0;
- }
-
- private boolean isPairingWithAntiSpoofingPublicKey() {
- return isPairingWithAntiSpoofingPublicKey(mPairingKey);
- }
-
- private boolean isPairingWithAntiSpoofingPublicKey(@Nullable byte[] key) {
- return key != null && key.length == EllipticCurveDiffieHellmanExchange.PUBLIC_KEY_LENGTH;
- }
-
- /**
- * Creates and writes an account key to the provided mac address.
- */
- @Nullable
- private byte[] doWriteAccountKey(byte[] accountKey, String macAddress)
- throws InterruptedException, ExecutionException, TimeoutException, BluetoothException {
- byte[] localPairingSecret = mPairingSecret;
- if (localPairingSecret == null) {
- Log.w(TAG, "Pairing secret was null, account key couldn't be encrypted or written.");
- return null;
- }
- if (!mPreferences.getSkipDisconnectingGattBeforeWritingAccountKey()) {
- try (ScopedTiming scopedTiming = new ScopedTiming(mTimingLogger,
- "Close GATT and sleep")) {
- // Make a new connection instead of reusing gattConnection, because this is
- // post-pairing and we need an encrypted connection.
- mGattConnectionManager.closeConnection();
- // Sleep before re-connecting to gatt, for writing account key, could increase
- // stability.
- Thread.sleep(mPreferences.getWriteAccountKeySleepMillis());
- }
- }
-
- byte[] encryptedKey;
- try (ScopedTiming scopedTiming = new ScopedTiming(mTimingLogger, "Encrypt key")) {
- encryptedKey = AesEcbSingleBlockEncryption.encrypt(localPairingSecret, accountKey);
- } catch (GeneralSecurityException e) {
- Log.w("Failed to encrypt key.", e);
- return null;
- }
-
- for (int i = 1; i <= mPreferences.getNumWriteAccountKeyAttempts(); i++) {
- mEventLogger.setCurrentEvent(EventCode.WRITE_ACCOUNT_KEY);
- try (ScopedTiming scopedTiming = new ScopedTiming(mTimingLogger,
- "Write key via GATT #" + i)) {
- writeAccountKey(encryptedKey, macAddress);
- mEventLogger.logCurrentEventSucceeded();
- return accountKey;
- } catch (BluetoothException e) {
- Log.w("Error writing account key attempt " + i + " of " + mPreferences
- .getNumWriteAccountKeyAttempts(), e);
- mEventLogger.logCurrentEventFailed(e);
- // Retry with a while for stability.
- Thread.sleep(mPreferences.getWriteAccountKeySleepMillis());
- }
- }
- return null;
- }
-
- private byte[] createAccountKey() throws NoSuchAlgorithmException {
- return AccountKeyGenerator.createAccountKey();
- }
-
- @VisibleForTesting
- boolean shouldWriteAccountKeyForExistingCase(byte[] existingAccountKey) {
- if (!mPreferences.getKeepSameAccountKeyWrite()) {
- Log.i(TAG,
- "The provider has already paired with the account, skip writing account key.");
- return false;
- }
- if (existingAccountKey[0] != AccountKeyCharacteristic.TYPE) {
- Log.i(TAG,
- "The provider has already paired with the account, but accountKey[0] != 0x04."
- + " Forget the device from the account and re-try");
-
- return false;
- }
- Log.i(TAG, "The provider has already paired with the account, still write the same account "
- + "key.");
- return true;
- }
-
- /**
- * Performs a key-based pairing request handshake to authenticate and get the remote device's
- * public address.
- *
- * @param key is described in {@link #pair(byte[])}
- */
- @VisibleForTesting
- SharedSecret handshakeForKeyBasedPairing(byte[] key)
- throws InterruptedException, ExecutionException, TimeoutException, BluetoothException,
- GeneralSecurityException, PairingException {
- // We may also initialize gattConnectionManager of prepareForHandshake() that will be used
- // in registerNotificationForNamePacket(), so we need to call it here.
- HandshakeHandler handshakeHandler = prepareForHandshake();
- KeyBasedPairingRequest.Builder keyBasedPairingRequestBuilder =
- new KeyBasedPairingRequest.Builder()
- .setVerificationData(BluetoothAddress.decode(mBleAddress));
- if (mProviderInitiatesBonding) {
- keyBasedPairingRequestBuilder
- .addFlag(KeyBasedPairingRequestFlag.PROVIDER_INITIATES_BONDING);
- }
- // Seeker only request provider device name in initial pairing.
- if (mPreferences.getEnableNamingCharacteristic() && isPairingWithAntiSpoofingPublicKey(
- key)) {
- keyBasedPairingRequestBuilder.addFlag(KeyBasedPairingRequestFlag.REQUEST_DEVICE_NAME);
- // Register listener to receive name characteristic response from provider.
- registerNotificationForNamePacket();
- }
- if (mPreferences.getIsRetroactivePairing()) {
- keyBasedPairingRequestBuilder
- .addFlag(KeyBasedPairingRequestFlag.REQUEST_RETROACTIVE_PAIR);
- keyBasedPairingRequestBuilder.setSeekerPublicAddress(
- Preconditions.checkNotNull(BluetoothAddress.getPublicAddress(mContext)));
- }
-
- return performHandshakeWithRetryAndSignalLostCheck(
- handshakeHandler, key, keyBasedPairingRequestBuilder.build(), /* withRetry= */
- true);
- }
-
- /**
- * Performs an action-over-BLE request handshake for authentication, i.e. to identify the shared
- * secret. The given key should be the account key.
- */
- private SharedSecret handshakeForActionOverBle(byte[] key,
- @AdditionalDataType int additionalDataType)
- throws InterruptedException, ExecutionException, TimeoutException, BluetoothException,
- GeneralSecurityException, PairingException {
- HandshakeHandler handshakeHandler = prepareForHandshake();
- return performHandshakeWithRetryAndSignalLostCheck(
- handshakeHandler,
- key,
- new ActionOverBle.Builder()
- .setVerificationData(BluetoothAddress.decode(mBleAddress))
- .setAdditionalDataType(additionalDataType)
- .build(),
- /* withRetry= */ false);
- }
-
- private HandshakeHandler prepareForHandshake() {
- if (mGattConnectionManager == null) {
- mGattConnectionManager =
- new GattConnectionManager(
- mContext,
- mPreferences,
- mEventLogger,
- mBluetoothAdapter,
- this::toggleBluetooth,
- mBleAddress,
- mTimingLogger,
- mFastPairSignalChecker,
- isPairingWithAntiSpoofingPublicKey());
- }
- if (mHandshakeHandlerForTest != null) {
- Log.w(TAG, "Use handshakeHandlerForTest!");
- return verifyNotNull(mHandshakeHandlerForTest);
- }
- return new HandshakeHandler(
- mGattConnectionManager, mBleAddress, mPreferences, mEventLogger,
- mFastPairSignalChecker);
- }
-
- @VisibleForTesting
- void setHandshakeHandlerForTest(@Nullable HandshakeHandler handshakeHandlerForTest) {
- this.mHandshakeHandlerForTest = handshakeHandlerForTest;
- }
-
- private SharedSecret performHandshakeWithRetryAndSignalLostCheck(
- HandshakeHandler handshakeHandler,
- byte[] key,
- HandshakeMessage handshakeMessage,
- boolean withRetry)
- throws GeneralSecurityException, ExecutionException, BluetoothException,
- InterruptedException, TimeoutException, PairingException {
- SharedSecret handshakeResult =
- withRetry
- ? handshakeHandler.doHandshakeWithRetryAndSignalLostCheck(
- key, handshakeMessage, mRescueFromError)
- : handshakeHandler.doHandshake(key, handshakeMessage);
- // TODO: Try to remove these two global variables, publicAddress and pairingSecret.
- mPublicAddress = handshakeResult.getAddress();
- mPairingSecret = handshakeResult.getKey();
- return handshakeResult;
- }
-
- private void toggleBluetooth()
- throws InterruptedException, ExecutionException, TimeoutException {
- if (!mPreferences.getToggleBluetoothOnFailure()) {
- return;
- }
-
- Log.i(TAG, "Turning Bluetooth off.");
- mEventLogger.setCurrentEvent(EventCode.DISABLE_BLUETOOTH);
- mBluetoothAdapter.unwrap().disable();
- disableBle(mBluetoothAdapter.unwrap());
- try {
- waitForBluetoothState(android.bluetooth.BluetoothAdapter.STATE_OFF);
- mEventLogger.logCurrentEventSucceeded();
- } catch (TimeoutException e) {
- mEventLogger.logCurrentEventFailed(e);
- // Soldier on despite failing to turn off Bluetooth. We can't control whether other
- // clients (even inside GCore) kept it enabled in BLE-only mode.
- Log.w(TAG, "Bluetooth still on. BluetoothAdapter state="
- + getBleState(mBluetoothAdapter.unwrap()), e);
- }
-
- // Note: Intentionally don't re-enable BLE-only mode, because we don't know which app
- // enabled it. The client app should listen to Bluetooth events and enable as necessary
- // (because the user can toggle at any time; e.g. via Airplane mode).
- Log.i(TAG, "Turning Bluetooth on.");
- mEventLogger.setCurrentEvent(EventCode.ENABLE_BLUETOOTH);
- mBluetoothAdapter.unwrap().enable();
- waitForBluetoothState(android.bluetooth.BluetoothAdapter.STATE_ON);
- mEventLogger.logCurrentEventSucceeded();
- }
-
- private void waitForBluetoothState(int state)
- throws TimeoutException, ExecutionException, InterruptedException {
- waitForBluetoothStateUsingPolling(state);
- }
-
- private void waitForBluetoothStateUsingPolling(int state) throws TimeoutException {
- // There's a bug where we (pretty often!) never get the broadcast for STATE_ON or STATE_OFF.
- // So poll instead.
- long start = SystemClock.elapsedRealtime();
- long timeoutMillis = mPreferences.getBluetoothToggleTimeoutSeconds() * 1000L;
- while (SystemClock.elapsedRealtime() - start < timeoutMillis) {
- if (state == getBleState(mBluetoothAdapter.unwrap())) {
- break;
- }
- SystemClock.sleep(mPreferences.getBluetoothStatePollingMillis());
- }
-
- if (state != getBleState(mBluetoothAdapter.unwrap())) {
- throw new TimeoutException(
- String.format(
- Locale.getDefault(),
- "Timed out waiting for state %d, current state is %d",
- state,
- getBleState(mBluetoothAdapter.unwrap())));
- }
- }
-
- private BrEdrHandoverInformation getBrEdrHandoverInformation(BluetoothGattConnection connection)
- throws BluetoothException, TdsException, InterruptedException, ExecutionException,
- TimeoutException {
- Log.i(TAG, "Connecting GATT server to BLE address=" + maskBluetoothAddress(mBleAddress));
- Log.i(TAG, "Telling device to become discoverable");
- mEventLogger.setCurrentEvent(EventCode.BR_EDR_HANDOVER_WRITE_CONTROL_POINT_REQUEST);
- ChangeObserver changeObserver =
- connection.enableNotification(
- TransportDiscoveryService.ID,
- TransportDiscoveryService.ControlPointCharacteristic.ID);
- connection.writeCharacteristic(
- TransportDiscoveryService.ID,
- TransportDiscoveryService.ControlPointCharacteristic.ID,
- TDS_CONTROL_POINT_REQUEST);
-
- byte[] response =
- changeObserver.waitForUpdate(
- TimeUnit.SECONDS.toMillis(mPreferences.getGattOperationTimeoutSeconds()));
- @ResultCode int resultCode = fromTdsControlPointIndication(response);
- if (resultCode != ResultCode.SUCCESS) {
- throw new TdsException(
- BrEdrHandoverErrorCode.CONTROL_POINT_RESULT_CODE_NOT_SUCCESS,
- "TDS Control Point result code (%s) was not success in response %s",
- resultCode,
- base16().lowerCase().encode(response));
- }
- mEventLogger.logCurrentEventSucceeded();
- return new BrEdrHandoverInformation(
- getAddressFromBrEdrConnection(connection),
- getProfilesFromBrEdrConnection(connection));
- }
-
- private byte[] getAddressFromBrEdrConnection(BluetoothGattConnection connection)
- throws BluetoothException, TdsException {
- Log.i(TAG, "Getting Bluetooth MAC");
- mEventLogger.setCurrentEvent(EventCode.BR_EDR_HANDOVER_READ_BLUETOOTH_MAC);
- byte[] brHandoverData =
- connection.readCharacteristic(
- TransportDiscoveryService.ID,
- to128BitUuid(mPreferences.getBrHandoverDataCharacteristicId()));
- if (brHandoverData == null || brHandoverData.length < 7) {
- throw new TdsException(
- BrEdrHandoverErrorCode.BLUETOOTH_MAC_INVALID,
- "Bluetooth MAC not contained in BR handover data: %s",
- brHandoverData != null ? base16().lowerCase().encode(brHandoverData)
- : "(none)");
- }
- byte[] bluetoothAddress =
- new Bytes.Value(Arrays.copyOfRange(brHandoverData, 1, 7), ByteOrder.LITTLE_ENDIAN)
- .getBytes(ByteOrder.BIG_ENDIAN);
- mEventLogger.logCurrentEventSucceeded();
- return bluetoothAddress;
- }
-
- private short[] getProfilesFromBrEdrConnection(BluetoothGattConnection connection) {
- mEventLogger.setCurrentEvent(EventCode.BR_EDR_HANDOVER_READ_TRANSPORT_BLOCK);
- try {
- byte[] transportBlock =
- connection.readDescriptor(
- TransportDiscoveryService.ID,
- to128BitUuid(mPreferences.getBluetoothSigDataCharacteristicId()),
- to128BitUuid(mPreferences.getBrTransportBlockDataDescriptorId()));
- Log.i(TAG, "Got transport block: " + base16().lowerCase().encode(transportBlock));
- short[] profiles = getSupportedProfiles(transportBlock);
- mEventLogger.logCurrentEventSucceeded();
- return profiles;
- } catch (BluetoothException | TdsException | ParseException e) {
- Log.w(TAG, "Failed to get supported profiles from transport block.", e);
- mEventLogger.logCurrentEventFailed(e);
- }
- return new short[0];
- }
-
- @VisibleForTesting
- boolean writeNameToProvider(@Nullable String deviceName, @Nullable String address)
- throws InterruptedException, TimeoutException, ExecutionException {
- if (deviceName == null || address == null) {
- Log.i(TAG, "writeNameToProvider fail because provider name or address is null.");
- return false;
- }
- if (mPairingSecret == null) {
- Log.i(TAG, "writeNameToProvider fail because no pairingSecret.");
- return false;
- }
- byte[] encryptedDeviceNamePacket;
- try (ScopedTiming scopedTiming = new ScopedTiming(mTimingLogger, "Encode device name")) {
- encryptedDeviceNamePacket =
- NamingEncoder.encodeNamingPacket(mPairingSecret, deviceName);
- } catch (GeneralSecurityException e) {
- Log.w(TAG, "Failed to encrypt device name.", e);
- return false;
- }
-
- for (int i = 1; i <= mPreferences.getNumWriteAccountKeyAttempts(); i++) {
- mEventLogger.setCurrentEvent(EventCode.WRITE_DEVICE_NAME);
- try {
- writeDeviceName(encryptedDeviceNamePacket, address);
- mEventLogger.logCurrentEventSucceeded();
- return true;
- } catch (BluetoothException e) {
- Log.w(TAG, "Error writing name attempt " + i + " of "
- + mPreferences.getNumWriteAccountKeyAttempts());
- mEventLogger.logCurrentEventFailed(e);
- // Reuses the existing preference because the same usage.
- Thread.sleep(mPreferences.getWriteAccountKeySleepMillis());
- }
- }
- return false;
- }
-
- private void writeAccountKey(byte[] encryptedAccountKey, String address)
- throws BluetoothException, InterruptedException, ExecutionException, TimeoutException {
- Log.i(TAG, "Writing account key to address=" + maskBluetoothAddress(address));
- BluetoothGattConnection connection = mGattConnectionManager.getConnection();
- connection.setOperationTimeout(
- TimeUnit.SECONDS.toMillis(mPreferences.getGattOperationTimeoutSeconds()));
- UUID characteristicUuid = AccountKeyCharacteristic.getId(connection);
- connection.writeCharacteristic(FastPairService.ID, characteristicUuid, encryptedAccountKey);
- Log.i(TAG,
- "Finished writing encrypted account key=" + base16().encode(encryptedAccountKey));
- }
-
- private void writeDeviceName(byte[] naming, String address)
- throws BluetoothException, InterruptedException, ExecutionException, TimeoutException {
- Log.i(TAG, "Writing new device name to address=" + maskBluetoothAddress(address));
- BluetoothGattConnection connection = mGattConnectionManager.getConnection();
- connection.setOperationTimeout(
- TimeUnit.SECONDS.toMillis(mPreferences.getGattOperationTimeoutSeconds()));
- UUID characteristicUuid = NameCharacteristic.getId(connection);
- connection.writeCharacteristic(FastPairService.ID, characteristicUuid, naming);
- Log.i(TAG, "Finished writing new device name=" + base16().encode(naming));
- }
-
- /**
- * Reads firmware version after write account key to provider since simulator is more stable to
- * read firmware version in initial gatt connection. This function will also read firmware when
- * detect bloomfilter. Need to verify this after real device come out. TODO(b/130592473)
- */
- @Nullable
- public String readFirmwareVersion()
- throws BluetoothException, InterruptedException, ExecutionException, TimeoutException {
- if (!TextUtils.isEmpty(sInitialConnectionFirmwareVersion)) {
- String result = sInitialConnectionFirmwareVersion;
- sInitialConnectionFirmwareVersion = null;
- return result;
- }
- if (mGattConnectionManager == null) {
- mGattConnectionManager =
- new GattConnectionManager(
- mContext,
- mPreferences,
- mEventLogger,
- mBluetoothAdapter,
- this::toggleBluetooth,
- mBleAddress,
- mTimingLogger,
- mFastPairSignalChecker,
- /* setMtu= */ true);
- mGattConnectionManager.closeConnection();
- }
- if (sTestMode) {
- return null;
- }
- BluetoothGattConnection connection = mGattConnectionManager.getConnection();
- connection.setOperationTimeout(
- TimeUnit.SECONDS.toMillis(mPreferences.getGattOperationTimeoutSeconds()));
-
- try {
- String firmwareVersion =
- new String(
- connection.readCharacteristic(
- FastPairService.ID,
- to128BitUuid(
- mPreferences.getFirmwareVersionCharacteristicId())));
- Log.i(TAG, "FastPair: Got the firmware info version number = " + firmwareVersion);
- mGattConnectionManager.closeConnection();
- return firmwareVersion;
- } catch (BluetoothException e) {
- Log.i(TAG, "FastPair: can't read firmware characteristic.", e);
- mGattConnectionManager.closeConnection();
- return null;
- }
- }
-
- @VisibleForTesting
- @Nullable
- String getInitialConnectionFirmware() {
- return sInitialConnectionFirmwareVersion;
- }
-
- private void registerNotificationForNamePacket()
- throws BluetoothException, InterruptedException, ExecutionException, TimeoutException {
- Log.i(TAG,
- "register for the device name response from address=" + maskBluetoothAddress(
- mBleAddress));
-
- BluetoothGattConnection gattConnection = mGattConnectionManager.getConnection();
- gattConnection.setOperationTimeout(
- TimeUnit.SECONDS.toMillis(mPreferences.getGattOperationTimeoutSeconds()));
- try {
- mDeviceNameReceiver = new DeviceNameReceiver(gattConnection);
- } catch (BluetoothException e) {
- Log.i(TAG, "Can't register for device name response, no naming characteristic.");
- return;
- }
- }
-
- private short[] getSupportedProfiles(BluetoothDevice device) {
- short[] supportedProfiles = getCachedUuids(device);
- if (supportedProfiles.length == 0 && mPreferences.getNumSdpAttemptsAfterBonded() > 0) {
- supportedProfiles =
- attemptGetBluetoothClassicProfiles(device,
- mPreferences.getNumSdpAttemptsAfterBonded());
- }
- if (supportedProfiles.length == 0) {
- supportedProfiles = Constants.getSupportedProfiles();
- Log.w(TAG, "Attempting to connect constants profiles, "
- + Arrays.toString(supportedProfiles));
- } else {
- Log.i(TAG,
- "Attempting to connect device profiles, " + Arrays.toString(supportedProfiles));
- }
- return supportedProfiles;
- }
-
- private static short[] getSupportedProfiles(byte[] transportBlock)
- throws TdsException, ParseException {
- if (transportBlock == null || transportBlock.length < 4) {
- throw new TdsException(
- BrEdrHandoverErrorCode.TRANSPORT_BLOCK_INVALID,
- "Transport Block null or too short: %s",
- base16().lowerCase().encode(transportBlock));
- }
- int transportDataLength = transportBlock[2];
- if (transportBlock.length < 3 + transportDataLength) {
- throw new TdsException(
- BrEdrHandoverErrorCode.TRANSPORT_BLOCK_INVALID,
- "Transport Block has wrong length byte: %s",
- base16().lowerCase().encode(transportBlock));
- }
- byte[] transportData = Arrays.copyOfRange(transportBlock, 3, 3 + transportDataLength);
- for (Ltv ltv : Ltv.parse(transportData)) {
- int uuidLength = uuidLength(ltv.mType);
- // We currently only support a single list of 2-byte UUIDs.
- // TODO(b/37539535): Support multiple lists, and longer (32-bit, 128-bit) IDs?
- if (uuidLength == 2) {
- return toShorts(ByteOrder.LITTLE_ENDIAN, ltv.mValue);
- }
- }
- return new short[0];
- }
-
- /**
- * Returns 0 if the type is not one of the UUID list types; otherwise returns length in bytes.
- */
- private static int uuidLength(byte dataType) {
- switch (dataType) {
- case TransportDiscoveryService.SERVICE_UUIDS_16_BIT_LIST_TYPE:
- return 2;
- case TransportDiscoveryService.SERVICE_UUIDS_32_BIT_LIST_TYPE:
- return 4;
- case TransportDiscoveryService.SERVICE_UUIDS_128_BIT_LIST_TYPE:
- return 16;
- default:
- return 0;
- }
- }
-
- private short[] attemptGetBluetoothClassicProfiles(BluetoothDevice device, int numSdpAttempts) {
- // The docs say that if fetchUuidsWithSdp() has an error or "takes a long time", we get an
- // intent containing only the stuff in the cache (i.e. nothing). Retry a few times.
- short[] supportedProfiles = null;
- for (int i = 1; i <= numSdpAttempts; i++) {
- mEventLogger.setCurrentEvent(EventCode.GET_PROFILES_VIA_SDP);
- try (ScopedTiming scopedTiming =
- new ScopedTiming(mTimingLogger,
- "Get BR/EDR handover information via SDP #" + i)) {
- supportedProfiles = getSupportedProfilesViaBluetoothClassic(device);
- } catch (ExecutionException | InterruptedException | TimeoutException e) {
- // Ignores and retries if needed.
- }
- if (supportedProfiles != null && supportedProfiles.length != 0) {
- mEventLogger.logCurrentEventSucceeded();
- break;
- } else {
- mEventLogger.logCurrentEventFailed(new TimeoutException());
- Log.w(TAG, "SDP returned no UUIDs from " + maskBluetoothAddress(device.getAddress())
- + ", assuming timeout (attempt " + i + " of " + numSdpAttempts + ").");
- }
- }
- return (supportedProfiles == null) ? new short[0] : supportedProfiles;
- }
-
- private short[] getSupportedProfilesViaBluetoothClassic(BluetoothDevice device)
- throws ExecutionException, InterruptedException, TimeoutException {
- Log.i(TAG, "Getting supported profiles via SDP (Bluetooth Classic) for "
- + maskBluetoothAddress(device.getAddress()));
- try (DeviceIntentReceiver supportedProfilesReceiver =
- DeviceIntentReceiver.oneShotReceiver(
- mContext, mPreferences, device, BluetoothDevice.ACTION_UUID)) {
- device.fetchUuidsWithSdp();
- supportedProfilesReceiver.await(mPreferences.getSdpTimeoutSeconds(), TimeUnit.SECONDS);
- }
- return getCachedUuids(device);
- }
-
- private static short[] getCachedUuids(BluetoothDevice device) {
- ParcelUuid[] parcelUuids = device.getUuids();
- Log.i(TAG, "Got supported UUIDs: " + Arrays.toString(parcelUuids));
- if (parcelUuids == null) {
- // The OS can return null.
- parcelUuids = new ParcelUuid[0];
- }
-
- List shortUuids = new ArrayList<>(parcelUuids.length);
- for (ParcelUuid parcelUuid : parcelUuids) {
- UUID uuid = parcelUuid.getUuid();
- if (BluetoothUuids.is16BitUuid(uuid)) {
- shortUuids.add(get16BitUuid(uuid));
- }
- }
- return Shorts.toArray(shortUuids);
- }
-
- private void callbackOnPaired() {
- if (mPairedCallback != null) {
- mPairedCallback.onPaired(mPublicAddress != null ? mPublicAddress : mBleAddress);
- }
- }
-
- private void callbackOnGetAddress(String address) {
- if (mOnGetBluetoothAddressCallback != null) {
- mOnGetBluetoothAddressCallback.onGetBluetoothAddress(address);
- }
- }
-
- private boolean validateBluetoothGattCharacteristic(
- BluetoothGattConnection connection, UUID characteristicUUID) {
- try (ScopedTiming scopedTiming =
- new ScopedTiming(mTimingLogger, "Get service characteristic list")) {
- List serviceCharacteristicList =
- connection.getService(FastPairService.ID).getCharacteristics();
- for (BluetoothGattCharacteristic characteristic : serviceCharacteristicList) {
- if (characteristicUUID.equals(characteristic.getUuid())) {
- Log.i(TAG, "characteristic is exists, uuid = " + characteristicUUID);
- return true;
- }
- }
- } catch (BluetoothException e) {
- Log.w(TAG, "Can't get service characteristic list.", e);
- }
- Log.i(TAG, "can't find characteristic, uuid = " + characteristicUUID);
- return false;
- }
-
- // This method is only for testing to make test method block until get name response or time
- // out.
- /**
- * Set name response countdown latch.
- */
- public void setNameResponseCountDownLatch(CountDownLatch countDownLatch) {
- if (mDeviceNameReceiver != null) {
- mDeviceNameReceiver.setCountDown(countDownLatch);
- Log.v(TAG, "set up nameResponseCountDown");
- }
- }
-
- private static int getBleState(android.bluetooth.BluetoothAdapter bluetoothAdapter) {
- // Can't use the public isLeEnabled() API, because it returns false for
- // STATE_BLE_TURNING_(ON|OFF). So if we assume false == STATE_OFF, that can be
- // very wrong.
- return getLeState(bluetoothAdapter);
- }
-
- private static int getLeState(android.bluetooth.BluetoothAdapter adapter) {
- try {
- return (Integer) Reflect.on(adapter).withMethod("getLeState").get();
- } catch (ReflectionException e) {
- Log.i(TAG, "Can't call getLeState", e);
- }
- return adapter.getState();
- }
-
- private static void disableBle(android.bluetooth.BluetoothAdapter adapter) {
- adapter.disableBLE();
- }
-
- /**
- * Handle the searching of Fast Pair history. Since there is only one public address using
- * during Fast Pair connection, {@link #isInPairedHistory(String)} only needs to be called once,
- * then the result is kept, and call {@link #getExistingAccountKey()} to get the result.
- */
- @VisibleForTesting
- static final class FastPairHistoryFinder {
-
- private @Nullable
- byte[] mExistingAccountKey;
- @Nullable
- private final List mHistoryItems;
-
- FastPairHistoryFinder(List historyItems) {
- this.mHistoryItems = historyItems;
- }
-
- @WorkerThread
- @VisibleForTesting
- boolean isInPairedHistory(String publicAddress) {
- if (mHistoryItems == null || mHistoryItems.isEmpty()) {
- return false;
- }
- for (FastPairHistoryItem item : mHistoryItems) {
- if (item.isMatched(BluetoothAddress.decode(publicAddress))) {
- mExistingAccountKey = item.accountKey().toByteArray();
- return true;
- }
- }
- return false;
- }
-
- // This function should be called after isInPairedHistory(). Or it will just return null.
- @WorkerThread
- @VisibleForTesting
- @Nullable
- byte[] getExistingAccountKey() {
- return mExistingAccountKey;
- }
- }
-
- private static final class DeviceNameReceiver {
-
- @GuardedBy("this")
- private @Nullable
- byte[] mEncryptedResponse;
-
- @GuardedBy("this")
- @Nullable
- private String mDecryptedDeviceName;
-
- @Nullable
- private CountDownLatch mResponseCountDown;
-
- DeviceNameReceiver(BluetoothGattConnection gattConnection) throws BluetoothException {
- UUID characteristicUuid = NameCharacteristic.getId(gattConnection);
- ChangeObserver observer =
- gattConnection.enableNotification(FastPairService.ID, characteristicUuid);
- observer.setListener(
- (byte[] value) -> {
- synchronized (DeviceNameReceiver.this) {
- Log.i(TAG, "DeviceNameReceiver: device name response size = "
- + value.length);
- // We don't decrypt it here because we may not finish handshaking and
- // the pairing
- // secret is not available.
- mEncryptedResponse = value;
- }
- // For testing to know we get the device name from provider.
- if (mResponseCountDown != null) {
- mResponseCountDown.countDown();
- Log.v(TAG, "Finish nameResponseCountDown.");
- }
- });
- }
-
- void setCountDown(CountDownLatch countDownLatch) {
- this.mResponseCountDown = countDownLatch;
- }
-
- synchronized @Nullable String getParsedResult(byte[] secret) {
- if (mDecryptedDeviceName != null) {
- return mDecryptedDeviceName;
- }
- if (mEncryptedResponse == null) {
- Log.i(TAG, "DeviceNameReceiver: no device name sent from the Provider.");
- return null;
- }
- try {
- mDecryptedDeviceName = NamingEncoder.decodeNamingPacket(secret, mEncryptedResponse);
- Log.i(TAG, "DeviceNameReceiver: decrypted provider's name from naming response, "
- + "name = " + mDecryptedDeviceName);
- } catch (GeneralSecurityException e) {
- Log.w(TAG, "DeviceNameReceiver: fail to parse the NameCharacteristic from provider"
- + ".", e);
- return null;
- }
- return mDecryptedDeviceName;
- }
- }
-
- static void checkFastPairSignal(
- FastPairSignalChecker fastPairSignalChecker,
- String currentAddress,
- Exception originalException)
- throws SignalLostException, SignalRotatedException {
- String newAddress = fastPairSignalChecker.getValidAddressForModelId(currentAddress);
- if (TextUtils.isEmpty(newAddress)) {
- throw new SignalLostException("Signal lost", originalException);
- } else if (!Ascii.equalsIgnoreCase(currentAddress, newAddress)) {
- throw new SignalRotatedException("Address rotated", newAddress, originalException);
- }
- }
-
- @VisibleForTesting
- public Preferences getPreferences() {
- return mPreferences;
- }
-}
diff --git a/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/FastPairHistoryItem.java b/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/FastPairHistoryItem.java
deleted file mode 100644
index e7748860e62e4d07073b4803f6d10eeecdef799e..0000000000000000000000000000000000000000
--- a/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/FastPairHistoryItem.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.nearby.common.bluetooth.fastpair;
-
-import static com.google.common.primitives.Bytes.concat;
-
-import com.google.common.hash.Hashing;
-import com.google.protobuf.ByteString;
-
-import java.util.Arrays;
-
-/**
- * It contains the sha256 of "account key + headset's public address" to identify the headset which
- * has paired with the account. Previously, account key is the only information for Fast Pair to
- * identify the headset, but Fast Pair can't identify the headset in initial pairing, there is no
- * account key data advertising from headset.
- */
-public class FastPairHistoryItem {
-
- private final ByteString mAccountKey;
- private final ByteString mSha256AccountKeyPublicAddress;
-
- FastPairHistoryItem(ByteString accountkey, ByteString sha256AccountKeyPublicAddress) {
- mAccountKey = accountkey;
- mSha256AccountKeyPublicAddress = sha256AccountKeyPublicAddress;
- }
-
- /**
- * Creates an instance of {@link FastPairHistoryItem}.
- *
- * @param accountKey key of an account that has paired with the headset.
- * @param sha256AccountKeyPublicAddress hash value of account key and headset's public address.
- */
- public static FastPairHistoryItem create(
- ByteString accountKey, ByteString sha256AccountKeyPublicAddress) {
- return new FastPairHistoryItem(accountKey, sha256AccountKeyPublicAddress);
- }
-
- ByteString accountKey() {
- return mAccountKey;
- }
-
- ByteString sha256AccountKeyPublicAddress() {
- return mSha256AccountKeyPublicAddress;
- }
-
- // Return true if the input public address is considered the same as this history item. Because
- // of privacy concern, Fast Pair does not really store the public address, it is identified by
- // the SHA256 of the account key and the public key.
- final boolean isMatched(byte[] publicAddress) {
- return Arrays.equals(
- sha256AccountKeyPublicAddress().toByteArray(),
- Hashing.sha256().hashBytes(concat(accountKey().toByteArray(), publicAddress))
- .asBytes());
- }
-}
-
diff --git a/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/GattConnectionManager.java b/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/GattConnectionManager.java
deleted file mode 100644
index e7ce4bfde675a4e45db4777aaf42542ec24a32b0..0000000000000000000000000000000000000000
--- a/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/GattConnectionManager.java
+++ /dev/null
@@ -1,278 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.nearby.common.bluetooth.fastpair;
-
-import static com.android.server.nearby.common.bluetooth.fastpair.AesEcbSingleBlockEncryption.AES_BLOCK_LENGTH;
-import static com.android.server.nearby.common.bluetooth.fastpair.BluetoothAddress.maskBluetoothAddress;
-import static com.android.server.nearby.common.bluetooth.fastpair.FastPairDualConnection.logRetrySuccessEvent;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import android.content.Context;
-import android.os.SystemClock;
-import android.util.Log;
-
-import androidx.annotation.Nullable;
-import androidx.annotation.VisibleForTesting;
-import androidx.core.util.Consumer;
-
-import com.android.server.nearby.common.bluetooth.BluetoothException;
-import com.android.server.nearby.common.bluetooth.BluetoothGattException;
-import com.android.server.nearby.common.bluetooth.BluetoothTimeoutException;
-import com.android.server.nearby.common.bluetooth.fastpair.TimingLogger.ScopedTiming;
-import com.android.server.nearby.common.bluetooth.gatt.BluetoothGattConnection;
-import com.android.server.nearby.common.bluetooth.gatt.BluetoothGattHelper;
-import com.android.server.nearby.common.bluetooth.gatt.BluetoothGattHelper.ConnectionOptions;
-import com.android.server.nearby.common.bluetooth.testability.android.bluetooth.BluetoothAdapter;
-import com.android.server.nearby.common.bluetooth.util.BluetoothOperationExecutor.BluetoothOperationTimeoutException;
-import com.android.server.nearby.intdefs.FastPairEventIntDefs.ErrorCode;
-import com.android.server.nearby.intdefs.NearbyEventIntDefs.EventCode;
-
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
-
-/**
- * Manager for working with Gatt connections.
- *
- *
This helper class allows for opening and closing GATT connections to a provided address.
- * Optionally, it can also support automatically reopening a connection in the case that it has been
- * closed when it's next needed through {@link Preferences#getAutomaticallyReconnectGattWhenNeeded}.
- */
-// TODO(b/202524672): Add class unit test.
-final class GattConnectionManager {
-
- private static final String TAG = GattConnectionManager.class.getSimpleName();
-
- private final Context mContext;
- private final Preferences mPreferences;
- private final EventLoggerWrapper mEventLogger;
- private final BluetoothAdapter mBluetoothAdapter;
- private final ToggleBluetoothTask mToggleBluetooth;
- private final String mAddress;
- private final TimingLogger mTimingLogger;
- private final boolean mSetMtu;
- @Nullable
- private final FastPairConnection.FastPairSignalChecker mFastPairSignalChecker;
- @Nullable
- private BluetoothGattConnection mGattConnection;
- private static boolean sTestMode = false;
-
- static void enableTestMode() {
- sTestMode = true;
- }
-
- GattConnectionManager(
- Context context,
- Preferences preferences,
- EventLoggerWrapper eventLogger,
- BluetoothAdapter bluetoothAdapter,
- ToggleBluetoothTask toggleBluetooth,
- String address,
- TimingLogger timingLogger,
- @Nullable FastPairConnection.FastPairSignalChecker fastPairSignalChecker,
- boolean setMtu) {
- this.mContext = context;
- this.mPreferences = preferences;
- this.mEventLogger = eventLogger;
- this.mBluetoothAdapter = bluetoothAdapter;
- this.mToggleBluetooth = toggleBluetooth;
- this.mAddress = address;
- this.mTimingLogger = timingLogger;
- this.mFastPairSignalChecker = fastPairSignalChecker;
- this.mSetMtu = setMtu;
- }
-
- /**
- * Gets a gatt connection to address. If this connection does not exist, it creates one.
- */
- BluetoothGattConnection getConnection()
- throws InterruptedException, ExecutionException, TimeoutException, BluetoothException {
- if (mGattConnection == null) {
- try {
- mGattConnection =
- connect(mAddress, /* checkSignalWhenFail= */ false,
- /* rescueFromError= */ null);
- } catch (SignalLostException | SignalRotatedException e) {
- // Impossible to happen here because we didn't do signal check.
- throw new ExecutionException("getConnection throws SignalLostException", e);
- }
- }
- return mGattConnection;
- }
-
- BluetoothGattConnection getConnectionWithSignalLostCheck(
- @Nullable Consumer rescueFromError)
- throws InterruptedException, ExecutionException, TimeoutException, BluetoothException,
- SignalLostException, SignalRotatedException {
- if (mGattConnection == null) {
- mGattConnection = connect(mAddress, /* checkSignalWhenFail= */ true,
- rescueFromError);
- }
- return mGattConnection;
- }
-
- /**
- * Closes the gatt connection when it is open.
- */
- void closeConnection() throws BluetoothException {
- if (mGattConnection != null) {
- try (ScopedTiming scopedTiming = new ScopedTiming(mTimingLogger, "Close GATT")) {
- mGattConnection.close();
- mGattConnection = null;
- }
- }
- }
-
- private BluetoothGattConnection connect(
- String address, boolean checkSignalWhenFail,
- @Nullable Consumer rescueFromError)
- throws InterruptedException, ExecutionException, TimeoutException, BluetoothException,
- SignalLostException, SignalRotatedException {
- int i = 1;
- boolean isRecoverable = true;
- long startElapsedRealtime = SystemClock.elapsedRealtime();
- BluetoothException lastException = null;
- mEventLogger.setCurrentEvent(EventCode.GATT_CONNECT);
- while (isRecoverable) {
- try (ScopedTiming scopedTiming =
- new ScopedTiming(mTimingLogger, "Connect GATT #" + i)) {
- Log.i(TAG, "Connecting to GATT server at " + maskBluetoothAddress(address));
- if (sTestMode) {
- return null;
- }
- BluetoothGattConnection connection =
- new BluetoothGattHelper(mContext, mBluetoothAdapter)
- .connect(
- mBluetoothAdapter.getRemoteDevice(address),
- getConnectionOptions(startElapsedRealtime));
- connection.setOperationTimeout(
- TimeUnit.SECONDS.toMillis(mPreferences.getGattOperationTimeoutSeconds()));
- if (mPreferences.getAutomaticallyReconnectGattWhenNeeded()) {
- connection.addCloseListener(
- () -> {
- Log.i(TAG, "Gatt connection with " + maskBluetoothAddress(address)
- + " closed.");
- mGattConnection = null;
- });
- }
- mEventLogger.logCurrentEventSucceeded();
- if (lastException != null) {
- logRetrySuccessEvent(EventCode.RECOVER_BY_RETRY_GATT, lastException,
- mEventLogger);
- }
- return connection;
- } catch (BluetoothException e) {
- lastException = e;
-
- boolean ableToRetry;
- if (mPreferences.getGattConnectRetryTimeoutMillis() > 0) {
- ableToRetry =
- (SystemClock.elapsedRealtime() - startElapsedRealtime)
- < mPreferences.getGattConnectRetryTimeoutMillis();
- Log.i(TAG, "Retry connecting GATT by timeout: " + ableToRetry);
- } else {
- ableToRetry = i < mPreferences.getNumAttempts();
- }
-
- if (mPreferences.getRetryGattConnectionAndSecretHandshake()) {
- if (isNoRetryError(mPreferences, e)) {
- ableToRetry = false;
- }
-
- if (ableToRetry) {
- if (rescueFromError != null) {
- rescueFromError.accept(
- e instanceof BluetoothOperationTimeoutException
- ? ErrorCode.SUCCESS_RETRY_GATT_TIMEOUT
- : ErrorCode.SUCCESS_RETRY_GATT_ERROR);
- }
- if (mFastPairSignalChecker != null && checkSignalWhenFail) {
- FastPairDualConnection
- .checkFastPairSignal(mFastPairSignalChecker, address, e);
- }
- }
- isRecoverable = ableToRetry;
- if (ableToRetry && mPreferences.getPairingRetryDelayMs() > 0) {
- SystemClock.sleep(mPreferences.getPairingRetryDelayMs());
- }
- } else {
- isRecoverable =
- ableToRetry
- && (e instanceof BluetoothOperationTimeoutException
- || e instanceof BluetoothTimeoutException
- || (e instanceof BluetoothGattException
- && ((BluetoothGattException) e).getGattErrorCode() == 133));
- }
- Log.w(TAG, "GATT connect attempt " + i + "of " + mPreferences.getNumAttempts()
- + " failed, " + (isRecoverable ? "recovering" : "permanently"), e);
- if (isRecoverable) {
- // If we're going to retry, log failure here. If we throw, an upper level will
- // log it.
- mToggleBluetooth.toggleBluetooth();
- i++;
- mEventLogger.logCurrentEventFailed(e);
- mEventLogger.setCurrentEvent(EventCode.GATT_CONNECT);
- }
- }
- }
- throw checkNotNull(lastException);
- }
-
- static boolean isNoRetryError(Preferences preferences, BluetoothException e) {
- return e instanceof BluetoothGattException
- && preferences
- .getGattConnectionAndSecretHandshakeNoRetryGattError()
- .contains(((BluetoothGattException) e).getGattErrorCode());
- }
-
- @VisibleForTesting
- long getTimeoutMs(long spentTime) {
- long timeoutInMs;
- if (mPreferences.getRetryGattConnectionAndSecretHandshake()) {
- timeoutInMs =
- spentTime < mPreferences.getGattConnectShortTimeoutRetryMaxSpentTimeMs()
- ? mPreferences.getGattConnectShortTimeoutMs()
- : mPreferences.getGattConnectLongTimeoutMs();
- } else {
- timeoutInMs = TimeUnit.SECONDS.toMillis(mPreferences.getGattConnectionTimeoutSeconds());
- }
- return timeoutInMs;
- }
-
- private ConnectionOptions getConnectionOptions(long startElapsedRealtime) {
- return createConnectionOptions(
- mSetMtu,
- getTimeoutMs(SystemClock.elapsedRealtime() - startElapsedRealtime));
- }
-
- public static ConnectionOptions createConnectionOptions(boolean setMtu, long timeoutInMs) {
- ConnectionOptions.Builder builder = ConnectionOptions.builder();
- if (setMtu) {
- // There are 3 overhead bytes added to BLE packets.
- builder.setMtu(
- AES_BLOCK_LENGTH + EllipticCurveDiffieHellmanExchange.PUBLIC_KEY_LENGTH + 3);
- }
- builder.setConnectionTimeoutMillis(timeoutInMs);
- return builder.build();
- }
-
- @VisibleForTesting
- void setGattConnection(BluetoothGattConnection gattConnection) {
- this.mGattConnection = gattConnection;
- }
-}
diff --git a/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/HandshakeHandler.java b/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/HandshakeHandler.java
deleted file mode 100644
index 984133b153e430141678ef0692fc01097a909eda..0000000000000000000000000000000000000000
--- a/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/HandshakeHandler.java
+++ /dev/null
@@ -1,560 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.nearby.common.bluetooth.fastpair;
-
-import static com.android.server.nearby.common.bluetooth.fastpair.AesEcbSingleBlockEncryption.AES_BLOCK_LENGTH;
-import static com.android.server.nearby.common.bluetooth.fastpair.AesEcbSingleBlockEncryption.decrypt;
-import static com.android.server.nearby.common.bluetooth.fastpair.AesEcbSingleBlockEncryption.encrypt;
-import static com.android.server.nearby.common.bluetooth.fastpair.BluetoothAddress.maskBluetoothAddress;
-import static com.android.server.nearby.common.bluetooth.fastpair.Constants.BLUETOOTH_ADDRESS_LENGTH;
-import static com.android.server.nearby.common.bluetooth.fastpair.Constants.FastPairService.KeyBasedPairingCharacteristic.ActionOverBleFlag.ADDITIONAL_DATA_CHARACTERISTIC;
-import static com.android.server.nearby.common.bluetooth.fastpair.Constants.FastPairService.KeyBasedPairingCharacteristic.ActionOverBleFlag.DEVICE_ACTION;
-import static com.android.server.nearby.common.bluetooth.fastpair.Constants.FastPairService.KeyBasedPairingCharacteristic.Request.ADDITIONAL_DATA_TYPE_INDEX;
-import static com.android.server.nearby.common.bluetooth.fastpair.Constants.FastPairService.KeyBasedPairingCharacteristic.Request.EVENT_ADDITIONAL_DATA_INDEX;
-import static com.android.server.nearby.common.bluetooth.fastpair.Constants.FastPairService.KeyBasedPairingCharacteristic.Request.EVENT_ADDITIONAL_DATA_LENGTH_INDEX;
-import static com.android.server.nearby.common.bluetooth.fastpair.Constants.FastPairService.KeyBasedPairingCharacteristic.Request.EVENT_CODE_INDEX;
-import static com.android.server.nearby.common.bluetooth.fastpair.Constants.FastPairService.KeyBasedPairingCharacteristic.Request.EVENT_GROUP_INDEX;
-import static com.android.server.nearby.common.bluetooth.fastpair.Constants.FastPairService.KeyBasedPairingCharacteristic.Request.FLAGS_INDEX;
-import static com.android.server.nearby.common.bluetooth.fastpair.Constants.FastPairService.KeyBasedPairingCharacteristic.Request.SEEKER_PUBLIC_ADDRESS_INDEX;
-import static com.android.server.nearby.common.bluetooth.fastpair.Constants.FastPairService.KeyBasedPairingCharacteristic.Request.TYPE_ACTION_OVER_BLE;
-import static com.android.server.nearby.common.bluetooth.fastpair.Constants.FastPairService.KeyBasedPairingCharacteristic.Request.TYPE_INDEX;
-import static com.android.server.nearby.common.bluetooth.fastpair.Constants.FastPairService.KeyBasedPairingCharacteristic.Request.TYPE_KEY_BASED_PAIRING_REQUEST;
-import static com.android.server.nearby.common.bluetooth.fastpair.Constants.FastPairService.KeyBasedPairingCharacteristic.Request.VERIFICATION_DATA_INDEX;
-import static com.android.server.nearby.common.bluetooth.fastpair.Constants.FastPairService.KeyBasedPairingCharacteristic.Request.VERIFICATION_DATA_LENGTH;
-import static com.android.server.nearby.common.bluetooth.fastpair.FastPairDualConnection.logRetrySuccessEvent;
-import static com.android.server.nearby.common.bluetooth.fastpair.GattConnectionManager.isNoRetryError;
-
-import static com.google.common.base.Verify.verifyNotNull;
-import static com.google.common.io.BaseEncoding.base16;
-import static com.google.common.primitives.Bytes.concat;
-
-import static java.util.concurrent.TimeUnit.SECONDS;
-
-import android.os.SystemClock;
-import android.util.Log;
-
-import androidx.annotation.Nullable;
-import androidx.annotation.VisibleForTesting;
-import androidx.core.util.Consumer;
-
-import com.android.server.nearby.common.bluetooth.BluetoothException;
-import com.android.server.nearby.common.bluetooth.BluetoothTimeoutException;
-import com.android.server.nearby.common.bluetooth.fastpair.Constants.FastPairService;
-import com.android.server.nearby.common.bluetooth.fastpair.Constants.FastPairService.AdditionalDataCharacteristic.AdditionalDataType;
-import com.android.server.nearby.common.bluetooth.fastpair.Constants.FastPairService.KeyBasedPairingCharacteristic;
-import com.android.server.nearby.common.bluetooth.fastpair.Constants.FastPairService.KeyBasedPairingCharacteristic.ActionOverBleFlag;
-import com.android.server.nearby.common.bluetooth.fastpair.Constants.FastPairService.KeyBasedPairingCharacteristic.KeyBasedPairingRequestFlag;
-import com.android.server.nearby.common.bluetooth.fastpair.Constants.FastPairService.KeyBasedPairingCharacteristic.Request;
-import com.android.server.nearby.common.bluetooth.fastpair.FastPairConnection.SharedSecret;
-import com.android.server.nearby.common.bluetooth.gatt.BluetoothGattConnection;
-import com.android.server.nearby.common.bluetooth.gatt.BluetoothGattConnection.ChangeObserver;
-import com.android.server.nearby.common.bluetooth.util.BluetoothOperationExecutor.BluetoothOperationTimeoutException;
-import com.android.server.nearby.intdefs.FastPairEventIntDefs.ErrorCode;
-import com.android.server.nearby.intdefs.NearbyEventIntDefs.EventCode;
-
-import java.security.GeneralSecurityException;
-import java.security.SecureRandom;
-import java.util.Arrays;
-import java.util.UUID;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeoutException;
-
-/**
- * Handles the handshake step of Fast Pair, the Provider's public address and the shared secret will
- * be disclosed during this step. It is the first step of all key-based operations, e.g. key-based
- * pairing and action over BLE.
- *
- * @see
- * Fastpair Spec Procedure
- */
-public class HandshakeHandler {
-
- private static final String TAG = HandshakeHandler.class.getSimpleName();
- private final GattConnectionManager mGattConnectionManager;
- private final String mProviderBleAddress;
- private final Preferences mPreferences;
- private final EventLoggerWrapper mEventLogger;
- @Nullable
- private final FastPairConnection.FastPairSignalChecker mFastPairSignalChecker;
-
- /**
- * Keeps the keys used during handshaking, generated by {@link #createKey(byte[])}.
- */
- private static final class Keys {
-
- private final byte[] mSharedSecret;
- private final byte[] mPublicKey;
-
- private Keys(byte[] sharedSecret, byte[] publicKey) {
- this.mSharedSecret = sharedSecret;
- this.mPublicKey = publicKey;
- }
- }
-
- public HandshakeHandler(
- GattConnectionManager gattConnectionManager,
- String bleAddress,
- Preferences preferences,
- EventLoggerWrapper eventLogger,
- @Nullable FastPairConnection.FastPairSignalChecker fastPairSignalChecker) {
- this.mGattConnectionManager = gattConnectionManager;
- this.mProviderBleAddress = bleAddress;
- this.mPreferences = preferences;
- this.mEventLogger = eventLogger;
- this.mFastPairSignalChecker = fastPairSignalChecker;
- }
-
- /**
- * Performs a handshake to authenticate and get the remote device's public address. Returns the
- * AES-128 key as the shared secret for this pairing session.
- */
- public SharedSecret doHandshake(byte[] key, HandshakeMessage message)
- throws GeneralSecurityException, InterruptedException, ExecutionException,
- TimeoutException, BluetoothException, PairingException {
- Keys keys = createKey(key);
- Log.i(TAG,
- "Handshake " + maskBluetoothAddress(mProviderBleAddress) + ", flags "
- + message.mFlags);
- byte[] handshakeResponse =
- processGattCommunication(
- createPacket(keys, message),
- SECONDS.toMillis(mPreferences.getGattOperationTimeoutSeconds()));
- String providerPublicAddress = decodeResponse(keys.mSharedSecret, handshakeResponse);
-
- return SharedSecret.create(keys.mSharedSecret, providerPublicAddress);
- }
-
- /**
- * Performs a handshake to authenticate and get the remote device's public address. Returns the
- * AES-128 key as the shared secret for this pairing session. Will retry and also performs
- * FastPair signal check if fails.
- */
- public SharedSecret doHandshakeWithRetryAndSignalLostCheck(
- byte[] key, HandshakeMessage message, @Nullable Consumer rescueFromError)
- throws GeneralSecurityException, InterruptedException, ExecutionException,
- TimeoutException, BluetoothException, PairingException {
- Keys keys = createKey(key);
- Log.i(TAG,
- "Handshake " + maskBluetoothAddress(mProviderBleAddress) + ", flags "
- + message.mFlags);
- int retryCount = 0;
- byte[] handshakeResponse = null;
- long startTime = SystemClock.elapsedRealtime();
- BluetoothException lastException = null;
- do {
- try {
- mEventLogger.setCurrentEvent(EventCode.SECRET_HANDSHAKE_GATT_COMMUNICATION);
- handshakeResponse =
- processGattCommunication(
- createPacket(keys, message),
- getTimeoutMs(SystemClock.elapsedRealtime() - startTime));
- mEventLogger.logCurrentEventSucceeded();
- if (lastException != null) {
- logRetrySuccessEvent(EventCode.RECOVER_BY_RETRY_HANDSHAKE, lastException,
- mEventLogger);
- }
- } catch (BluetoothException e) {
- lastException = e;
- long spentTime = SystemClock.elapsedRealtime() - startTime;
- Log.w(TAG, "Secret handshake failed, address="
- + maskBluetoothAddress(mProviderBleAddress)
- + ", spent time=" + spentTime + "ms, retryCount=" + retryCount);
- mEventLogger.logCurrentEventFailed(e);
-
- if (!mPreferences.getRetryGattConnectionAndSecretHandshake()) {
- throw e;
- }
-
- if (spentTime > mPreferences.getSecretHandshakeLongTimeoutRetryMaxSpentTimeMs()) {
- Log.w(TAG, "Spent too long time for handshake, timeInMs=" + spentTime);
- throw e;
- }
- if (isNoRetryError(mPreferences, e)) {
- throw e;
- }
-
- if (mFastPairSignalChecker != null) {
- FastPairDualConnection
- .checkFastPairSignal(mFastPairSignalChecker, mProviderBleAddress, e);
- }
- retryCount++;
- if (retryCount > mPreferences.getSecretHandshakeRetryAttempts()
- || ((e instanceof BluetoothOperationTimeoutException)
- && !mPreferences.getRetrySecretHandshakeTimeout())) {
- throw new HandshakeException("Fail on handshake!", e);
- }
- if (rescueFromError != null) {
- rescueFromError.accept(
- (e instanceof BluetoothTimeoutException
- || e instanceof BluetoothOperationTimeoutException)
- ? ErrorCode.SUCCESS_RETRY_SECRET_HANDSHAKE_TIMEOUT
- : ErrorCode.SUCCESS_RETRY_SECRET_HANDSHAKE_ERROR);
- }
- }
- } while (mPreferences.getRetryGattConnectionAndSecretHandshake()
- && handshakeResponse == null);
- if (retryCount > 0) {
- Log.i(TAG, "Secret handshake failed but restored by retry, retry count=" + retryCount);
- }
- String providerPublicAddress =
- decodeResponse(keys.mSharedSecret, verifyNotNull(handshakeResponse));
-
- return SharedSecret.create(keys.mSharedSecret, providerPublicAddress);
- }
-
- @VisibleForTesting
- long getTimeoutMs(long spentTime) {
- if (!mPreferences.getRetryGattConnectionAndSecretHandshake()) {
- return SECONDS.toMillis(mPreferences.getGattOperationTimeoutSeconds());
- } else {
- return spentTime < mPreferences.getSecretHandshakeShortTimeoutRetryMaxSpentTimeMs()
- ? mPreferences.getSecretHandshakeShortTimeoutMs()
- : mPreferences.getSecretHandshakeLongTimeoutMs();
- }
- }
-
- /**
- * If the given key is an ecc-256 public key (currently, we are using secp256r1), the shared
- * secret is generated by ECDH; if the input key is AES-128 key (should be the account key),
- * then it is the shared secret.
- */
- private Keys createKey(byte[] key) throws GeneralSecurityException {
- if (key.length == EllipticCurveDiffieHellmanExchange.PUBLIC_KEY_LENGTH) {
- EllipticCurveDiffieHellmanExchange exchange = EllipticCurveDiffieHellmanExchange
- .create();
- byte[] publicKey = exchange.getPublicKey();
- if (publicKey != null) {
- Log.i(TAG, "Handshake " + maskBluetoothAddress(mProviderBleAddress)
- + ", generates key by ECDH.");
- } else {
- throw new GeneralSecurityException("Failed to do ECDH.");
- }
- return new Keys(exchange.generateSecret(key), publicKey);
- } else if (key.length == AesEcbSingleBlockEncryption.KEY_LENGTH) {
- Log.i(TAG, "Handshake " + maskBluetoothAddress(mProviderBleAddress)
- + ", using the given secret.");
- return new Keys(key, new byte[0]);
- } else {
- throw new GeneralSecurityException("Key length is not correct: " + key.length);
- }
- }
-
- private static byte[] createPacket(Keys keys, HandshakeMessage message)
- throws GeneralSecurityException {
- byte[] encryptedMessage = encrypt(keys.mSharedSecret, message.getBytes());
- return concat(encryptedMessage, keys.mPublicKey);
- }
-
- private byte[] processGattCommunication(byte[] packet, long gattOperationTimeoutMS)
- throws BluetoothException, InterruptedException, ExecutionException, TimeoutException {
- BluetoothGattConnection gattConnection = mGattConnectionManager.getConnection();
- gattConnection.setOperationTimeout(gattOperationTimeoutMS);
- UUID characteristicUuid = KeyBasedPairingCharacteristic.getId(gattConnection);
- ChangeObserver changeObserver =
- gattConnection.enableNotification(FastPairService.ID, characteristicUuid);
-
- Log.i(TAG,
- "Writing handshake packet to address=" + maskBluetoothAddress(mProviderBleAddress));
- gattConnection.writeCharacteristic(FastPairService.ID, characteristicUuid, packet);
- Log.i(TAG, "Waiting handshake packet from address=" + maskBluetoothAddress(
- mProviderBleAddress));
- return changeObserver.waitForUpdate(gattOperationTimeoutMS);
- }
-
- private String decodeResponse(byte[] sharedSecret, byte[] response)
- throws PairingException, GeneralSecurityException {
- if (response.length != AES_BLOCK_LENGTH) {
- throw new PairingException(
- "Handshake failed because of incorrect response: " + base16().encode(response));
- }
- // 1 byte type, 6 bytes public address, remainder random salt.
- byte[] decryptedResponse = decrypt(sharedSecret, response);
- if (decryptedResponse[0] != KeyBasedPairingCharacteristic.Response.TYPE) {
- throw new PairingException(
- "Handshake response type incorrect: " + decryptedResponse[0]);
- }
- String address = BluetoothAddress.encode(Arrays.copyOfRange(decryptedResponse, 1, 7));
- Log.i(TAG, "Handshake success with public " + maskBluetoothAddress(address) + ", ble "
- + maskBluetoothAddress(mProviderBleAddress));
- return address;
- }
-
- /**
- * The base class for handshake message that contains the common data: message type, flags and
- * verification data.
- */
- abstract static class HandshakeMessage {
-
- final byte mType;
- final byte mFlags;
- private final byte[] mVerificationData;
-
- HandshakeMessage(Builder> builder) {
- this.mType = builder.mType;
- this.mVerificationData = builder.mVerificationData;
- this.mFlags = builder.mFlags;
- }
-
- abstract static class Builder> {
-
- byte mType;
- byte mFlags;
- private byte[] mVerificationData;
-
- abstract T getThis();
-
- T setVerificationData(byte[] verificationData) {
- if (verificationData.length != BLUETOOTH_ADDRESS_LENGTH) {
- throw new IllegalArgumentException(
- "Incorrect verification data length: " + verificationData.length + ".");
- }
- this.mVerificationData = verificationData;
- return getThis();
- }
- }
-
- /**
- * Constructs the base handshake message according to the format of Fast Pair spec.
- */
- byte[] constructBaseBytes() {
- byte[] rawMessage = new byte[Request.SIZE];
- new SecureRandom().nextBytes(rawMessage);
- rawMessage[TYPE_INDEX] = mType;
- rawMessage[FLAGS_INDEX] = mFlags;
-
- System.arraycopy(
- mVerificationData,
- /* srcPos= */ 0,
- rawMessage,
- VERIFICATION_DATA_INDEX,
- VERIFICATION_DATA_LENGTH);
- return rawMessage;
- }
-
- /**
- * Returns the raw handshake message.
- */
- abstract byte[] getBytes();
- }
-
- /**
- * Extends {@link HandshakeMessage} and contains the required data for key-based pairing
- * request.
- */
- public static class KeyBasedPairingRequest extends HandshakeMessage {
-
- @Nullable
- private final byte[] mSeekerPublicAddress;
-
- private KeyBasedPairingRequest(Builder builder) {
- super(builder);
- this.mSeekerPublicAddress = builder.mSeekerPublicAddress;
- }
-
- @Override
- byte[] getBytes() {
- byte[] rawMessage = constructBaseBytes();
- if (mSeekerPublicAddress != null) {
- System.arraycopy(
- mSeekerPublicAddress,
- /* srcPos= */ 0,
- rawMessage,
- SEEKER_PUBLIC_ADDRESS_INDEX,
- BLUETOOTH_ADDRESS_LENGTH);
- }
- Log.i(TAG,
- "Handshake Message: type (" + rawMessage[TYPE_INDEX] + "), flag ("
- + rawMessage[FLAGS_INDEX] + ").");
- return rawMessage;
- }
-
- /**
- * Builder class for key-based pairing request.
- */
- public static class Builder extends HandshakeMessage.Builder {
-
- @Nullable
- private byte[] mSeekerPublicAddress;
-
- /**
- * Adds flags without changing other flags.
- */
- public Builder addFlag(@KeyBasedPairingRequestFlag int flag) {
- this.mFlags |= (byte) flag;
- return this;
- }
-
- /**
- * Set seeker's public address.
- */
- public Builder setSeekerPublicAddress(byte[] seekerPublicAddress) {
- this.mSeekerPublicAddress = seekerPublicAddress;
- return this;
- }
-
- /**
- * Buulds KeyBasedPairigRequest.
- */
- public KeyBasedPairingRequest build() {
- mType = TYPE_KEY_BASED_PAIRING_REQUEST;
- return new KeyBasedPairingRequest(this);
- }
-
- @Override
- Builder getThis() {
- return this;
- }
- }
- }
-
- /**
- * Extends {@link HandshakeMessage} and contains the required data for action over BLE request.
- */
- public static class ActionOverBle extends HandshakeMessage {
-
- private final byte mEventGroup;
- private final byte mEventCode;
- @Nullable
- private final byte[] mEventData;
- private final byte mAdditionalDataType;
-
- private ActionOverBle(Builder builder) {
- super(builder);
- this.mEventGroup = builder.mEventGroup;
- this.mEventCode = builder.mEventCode;
- this.mEventData = builder.mEventData;
- this.mAdditionalDataType = builder.mAdditionalDataType;
- }
-
- @Override
- byte[] getBytes() {
- byte[] rawMessage = constructBaseBytes();
- StringBuilder stringBuilder =
- new StringBuilder(
- String.format(
- "type (%02X), flag (%02X)", rawMessage[TYPE_INDEX],
- rawMessage[FLAGS_INDEX]));
- if ((mFlags & (byte) DEVICE_ACTION) != 0) {
- rawMessage[EVENT_GROUP_INDEX] = mEventGroup;
- rawMessage[EVENT_CODE_INDEX] = mEventCode;
-
- if (mEventData != null) {
- rawMessage[EVENT_ADDITIONAL_DATA_LENGTH_INDEX] = (byte) mEventData.length;
- System.arraycopy(
- mEventData,
- /* srcPos= */ 0,
- rawMessage,
- EVENT_ADDITIONAL_DATA_INDEX,
- mEventData.length);
- } else {
- rawMessage[EVENT_ADDITIONAL_DATA_LENGTH_INDEX] = (byte) 0;
- }
- stringBuilder.append(
- String.format(
- ", group(%02X), code(%02X), length(%02X)",
- rawMessage[EVENT_GROUP_INDEX],
- rawMessage[EVENT_CODE_INDEX],
- rawMessage[EVENT_ADDITIONAL_DATA_LENGTH_INDEX]));
- }
- if ((mFlags & (byte) ADDITIONAL_DATA_CHARACTERISTIC) != 0) {
- rawMessage[ADDITIONAL_DATA_TYPE_INDEX] = mAdditionalDataType;
- stringBuilder.append(
- String.format(", data id(%02X)", rawMessage[ADDITIONAL_DATA_TYPE_INDEX]));
- }
- Log.i(TAG, "Handshake Message: " + stringBuilder);
- return rawMessage;
- }
-
- /**
- * Builder class for action over BLE request.
- */
- public static class Builder extends HandshakeMessage.Builder {
-
- private byte mEventGroup;
- private byte mEventCode;
- @Nullable
- private byte[] mEventData;
- private byte mAdditionalDataType;
-
- // Adds a flag to this handshake message. This can be called repeatedly for adding
- // different preference.
-
- /**
- * Adds flag without changing other flags.
- */
- public Builder addFlag(@ActionOverBleFlag int flag) {
- this.mFlags |= (byte) flag;
- return this;
- }
-
- /**
- * Set event group and event code.
- */
- public Builder setEvent(int eventGroup, int eventCode) {
- this.mFlags |= (byte) DEVICE_ACTION;
- this.mEventGroup = (byte) (eventGroup & 0xFF);
- this.mEventCode = (byte) (eventCode & 0xFF);
- return this;
- }
-
- /**
- * Set event additional data.
- */
- public Builder setEventAdditionalData(byte[] data) {
- this.mEventData = data;
- return this;
- }
-
- /**
- * Set event additional data type.
- */
- public Builder setAdditionalDataType(@AdditionalDataType int additionalDataType) {
- this.mFlags |= (byte) ADDITIONAL_DATA_CHARACTERISTIC;
- this.mAdditionalDataType = (byte) additionalDataType;
- return this;
- }
-
- @Override
- Builder getThis() {
- return this;
- }
-
- ActionOverBle build() {
- mType = TYPE_ACTION_OVER_BLE;
- return new ActionOverBle(this);
- }
- }
- }
-
- /**
- * Exception for handshake failure.
- */
- public static class HandshakeException extends PairingException {
-
- private final BluetoothException mOriginalException;
-
- @VisibleForTesting
- HandshakeException(String format, BluetoothException e) {
- super(format);
- mOriginalException = e;
- }
-
- public BluetoothException getOriginalException() {
- return mOriginalException;
- }
- }
-}
diff --git a/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/HeadsetPiece.java b/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/HeadsetPiece.java
deleted file mode 100644
index 26ff79fab58a3a0e533026e5314f9a243c373ff2..0000000000000000000000000000000000000000
--- a/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/HeadsetPiece.java
+++ /dev/null
@@ -1,239 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.nearby.common.bluetooth.fastpair;
-
-import android.net.Uri;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import androidx.annotation.Nullable;
-import androidx.core.content.FileProvider;
-
-import java.util.Arrays;
-import java.util.Objects;
-
-/**
- * This class is subclass of real headset. It contains image url, battery value and charging
- * status.
- */
-public class HeadsetPiece implements Parcelable {
- private int mLowLevelThreshold;
- private int mBatteryLevel;
- private String mImageUrl;
- private boolean mCharging;
- private Uri mImageContentUri;
-
- private HeadsetPiece(
- int lowLevelThreshold,
- int batteryLevel,
- String imageUrl,
- boolean charging,
- @Nullable Uri imageContentUri) {
- this.mLowLevelThreshold = lowLevelThreshold;
- this.mBatteryLevel = batteryLevel;
- this.mImageUrl = imageUrl;
- this.mCharging = charging;
- this.mImageContentUri = imageContentUri;
- }
-
- /**
- * Returns a builder of HeadsetPiece.
- */
- public static HeadsetPiece.Builder builder() {
- return new HeadsetPiece.Builder();
- }
-
- /**
- * The low level threshold.
- */
- public int lowLevelThreshold() {
- return mLowLevelThreshold;
- }
-
- /**
- * The battery level.
- */
- public int batteryLevel() {
- return mBatteryLevel;
- }
-
- /**
- * The web URL of the image.
- */
- public String imageUrl() {
- return mImageUrl;
- }
-
- /**
- * Whether the headset is charging.
- */
- public boolean charging() {
- return mCharging;
- }
-
- /**
- * The content Uri of the image if it could be downloaded from the web URL and generated through
- * {@link FileProvider#getUriForFile} successfully, otherwise null.
- */
- @Nullable
- public Uri imageContentUri() {
- return mImageContentUri;
- }
-
- /**
- * @return whether battery is low or not.
- */
- public boolean isBatteryLow() {
- return batteryLevel() <= lowLevelThreshold() && batteryLevel() >= 0 && !charging();
- }
-
- @Override
- public String toString() {
- return "HeadsetPiece{"
- + "lowLevelThreshold=" + mLowLevelThreshold + ", "
- + "batteryLevel=" + mBatteryLevel + ", "
- + "imageUrl=" + mImageUrl + ", "
- + "charging=" + mCharging + ", "
- + "imageContentUri=" + mImageContentUri
- + "}";
- }
-
- /**
- * Builder function for headset piece.
- */
- public static class Builder {
- private int mLowLevelThreshold;
- private int mBatteryLevel;
- private String mImageUrl;
- private boolean mCharging;
- private Uri mImageContentUri;
-
- /**
- * Set low level threshold.
- */
- public HeadsetPiece.Builder setLowLevelThreshold(int lowLevelThreshold) {
- this.mLowLevelThreshold = lowLevelThreshold;
- return this;
- }
-
- /**
- * Set battery level.
- */
- public HeadsetPiece.Builder setBatteryLevel(int level) {
- this.mBatteryLevel = level;
- return this;
- }
-
- /**
- * Set image url.
- */
- public HeadsetPiece.Builder setImageUrl(String url) {
- this.mImageUrl = url;
- return this;
- }
-
- /**
- * Set charging.
- */
- public HeadsetPiece.Builder setCharging(boolean charging) {
- this.mCharging = charging;
- return this;
- }
-
- /**
- * Set image content Uri.
- */
- public HeadsetPiece.Builder setImageContentUri(Uri uri) {
- this.mImageContentUri = uri;
- return this;
- }
-
- /**
- * Builds HeadSetPiece.
- */
- public HeadsetPiece build() {
- return new HeadsetPiece(mLowLevelThreshold, mBatteryLevel, mImageUrl, mCharging,
- mImageContentUri);
- }
- }
-
- @Override
- public final void writeToParcel(Parcel dest, int flags) {
- dest.writeString(imageUrl());
- dest.writeInt(lowLevelThreshold());
- dest.writeInt(batteryLevel());
- // Writes 1 if charging, otherwise 0.
- dest.writeByte((byte) (charging() ? 1 : 0));
- dest.writeParcelable(imageContentUri(), flags);
- }
-
- @Override
- public final int describeContents() {
- return 0;
- }
-
- public static final Creator CREATOR =
- new Creator() {
- @Override
- public HeadsetPiece createFromParcel(Parcel in) {
- String imageUrl = in.readString();
- return HeadsetPiece.builder()
- .setImageUrl(imageUrl != null ? imageUrl : "")
- .setLowLevelThreshold(in.readInt())
- .setBatteryLevel(in.readInt())
- .setCharging(in.readByte() != 0)
- .setImageContentUri(in.readParcelable(Uri.class.getClassLoader()))
- .build();
- }
-
- @Override
- public HeadsetPiece[] newArray(int size) {
- return new HeadsetPiece[size];
- }
- };
-
- @Override
- public final int hashCode() {
- return Arrays.hashCode(
- new Object[]{
- lowLevelThreshold(), batteryLevel(), imageUrl(), charging(),
- imageContentUri()
- });
- }
-
- @Override
- public final boolean equals(@Nullable Object other) {
- if (other == null) {
- return false;
- }
-
- if (this == other) {
- return true;
- }
-
- if (!(other instanceof HeadsetPiece)) {
- return false;
- }
-
- HeadsetPiece that = (HeadsetPiece) other;
- return lowLevelThreshold() == that.lowLevelThreshold()
- && batteryLevel() == that.batteryLevel()
- && Objects.equals(imageUrl(), that.imageUrl())
- && charging() == that.charging()
- && Objects.equals(imageContentUri(), that.imageContentUri());
- }
-}
diff --git a/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/HmacSha256.java b/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/HmacSha256.java
deleted file mode 100644
index cc7a300dbb3692a29adef4378ab71d91c3848878..0000000000000000000000000000000000000000
--- a/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/HmacSha256.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.nearby.common.bluetooth.fastpair;
-
-import static com.android.server.nearby.common.bluetooth.fastpair.AesCtrMultipleBlockEncryption.KEY_LENGTH;
-
-import androidx.annotation.VisibleForTesting;
-
-import java.security.GeneralSecurityException;
-
-import javax.crypto.Mac;
-import javax.crypto.spec.SecretKeySpec;
-
-/**
- * HMAC-SHA256 utility used to generate key-SHA256 based message authentication code. This is
- * specific for Fast Pair GATT connection exchanging data to verify both the data integrity and the
- * authentication of a message. It is defined as:
- *
- *
- *
SHA256(concat((key ^ opad),SHA256(concat((key ^ ipad), data)))), where
- *
key is the given secret extended to 64 bytes by concat(secret, ZEROS).
- *
opad is 64 bytes outer padding, consisting of repeated bytes valued 0x5c.
- *
ipad is 64 bytes inner padding, consisting of repeated bytes valued 0x36.
- *
- *
- */
-final class HmacSha256 {
- @VisibleForTesting static final int HMAC_SHA256_BLOCK_SIZE = 64;
-
- private HmacSha256() {}
-
- /**
- * Generates the HMAC for given parameters, this is specific for Fast Pair GATT connection
- * exchanging data which is encrypted using AES-CTR.
- *
- * @param secret 16 bytes shared secret.
- * @param data the data encrypted using AES-CTR and the given nonce.
- * @return HMAC-SHA256 result.
- */
- static byte[] build(byte[] secret, byte[] data) throws GeneralSecurityException {
- // Currently we only accept AES-128 key here, the second check is to secure we won't
- // modify KEY_LENGTH to > HMAC_SHA256_BLOCK_SIZE by mistake.
- if (secret.length != KEY_LENGTH) {
- throw new GeneralSecurityException("Incorrect key length, should be the AES-128 key.");
- }
- if (KEY_LENGTH > HMAC_SHA256_BLOCK_SIZE) {
- throw new GeneralSecurityException("KEY_LENGTH > HMAC_SHA256_BLOCK_SIZE!");
- }
-
- return buildWith64BytesKey(secret, data);
- }
-
- /**
- * Generates the HMAC for given parameters, this is specific for Fast Pair GATT connection
- * exchanging data which is encrypted using AES-CTR.
- *
- * @param secret 16 bytes shared secret.
- * @param data the data encrypted using AES-CTR and the given nonce.
- * @return HMAC-SHA256 result.
- */
- static byte[] buildWith64BytesKey(byte[] secret, byte[] data) throws GeneralSecurityException {
- if (secret.length > HMAC_SHA256_BLOCK_SIZE) {
- throw new GeneralSecurityException("KEY_LENGTH > HMAC_SHA256_BLOCK_SIZE!");
- }
-
- Mac mac = Mac.getInstance("HmacSHA256");
- SecretKeySpec keySpec = new SecretKeySpec(secret, "HmacSHA256");
- mac.init(keySpec);
-
- return mac.doFinal(data);
- }
-
- /**
- * Constant-time HMAC comparison to prevent a possible timing attack, e.g. time the same MAC
- * with all different first byte for a given ciphertext, the right one will take longer as it
- * will fail on the second byte's verification.
- *
- * @param hmac1 HMAC want to be compared with.
- * @param hmac2 HMAC want to be compared with.
- * @return true if and ony if the give 2 HMACs are identical and non-null.
- */
- static boolean compareTwoHMACs(byte[] hmac1, byte[] hmac2) {
- if (hmac1 == null || hmac2 == null) {
- return false;
- }
-
- if (hmac1.length != hmac2.length) {
- return false;
- }
- // This is for constant-time comparison, don't optimize it.
- int res = 0;
- for (int i = 0; i < hmac1.length; i++) {
- res |= hmac1[i] ^ hmac2[i];
- }
- return res == 0;
- }
-}
diff --git a/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/Ltv.java b/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/Ltv.java
deleted file mode 100644
index 88c9484d34a1ef1d6c7b17f07ab157a0a2789960..0000000000000000000000000000000000000000
--- a/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/Ltv.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.nearby.common.bluetooth.fastpair;
-
-import static com.google.common.io.BaseEncoding.base16;
-
-import com.google.common.primitives.Bytes;
-import com.google.errorprone.annotations.FormatMethod;
-import com.google.errorprone.annotations.FormatString;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-/**
- * A length, type, value (LTV) data block.
- */
-public class Ltv {
-
- private static final int SIZE_OF_LEN_TYPE = 2;
-
- final byte mType;
- final byte[] mValue;
-
- /**
- * Thrown if there's an error during {@link #parse}.
- */
- public static class ParseException extends Exception {
-
- @FormatMethod
- private ParseException(@FormatString String format, Object... objects) {
- super(String.format(format, objects));
- }
- }
-
- /**
- * Constructor.
- */
- public Ltv(byte type, byte... value) {
- this.mType = type;
- this.mValue = value;
- }
-
- /**
- * Parses a list of LTV blocks out of the input byte block.
- */
- static List parse(byte[] bytes) throws ParseException {
- List ltvs = new ArrayList<>();
- // The "+ 2" is for the length and type bytes.
- for (int valueLength, i = 0; i < bytes.length; i += SIZE_OF_LEN_TYPE + valueLength) {
- // - 1 since the length in the packet includes the type byte.
- valueLength = bytes[i] - 1;
- if (valueLength < 0 || bytes.length < i + SIZE_OF_LEN_TYPE + valueLength) {
- throw new ParseException(
- "Wrong length=%d at index=%d in LTVs=%s", bytes[i], i,
- base16().encode(bytes));
- }
- ltvs.add(new Ltv(bytes[i + 1], Arrays.copyOfRange(bytes, i + SIZE_OF_LEN_TYPE,
- i + SIZE_OF_LEN_TYPE + valueLength)));
- }
- return ltvs;
- }
-
- /**
- * Returns an LTV block, where length is mValue.length + 1 (for the type byte).
- */
- public byte[] getBytes() {
- return Bytes.concat(new byte[]{(byte) (mValue.length + 1), mType}, mValue);
- }
-}
diff --git a/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/MessageStreamHmacEncoder.java b/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/MessageStreamHmacEncoder.java
deleted file mode 100644
index b04cf7352afb3f45d1e705007bd7b4f01be72f2c..0000000000000000000000000000000000000000
--- a/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/MessageStreamHmacEncoder.java
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.nearby.common.bluetooth.fastpair;
-
-import static com.android.server.nearby.common.bluetooth.fastpair.AesCtrMultipleBlockEncryption.generateNonce;
-
-import static com.google.common.primitives.Bytes.concat;
-
-import java.security.GeneralSecurityException;
-import java.util.Arrays;
-
-/**
- * Message stream utilities for encoding raw packet with HMAC.
- *
- *
- */
-// TODO(b/202549655): remove existing Reflect usage. New usage is not allowed! No exception!
-public final class Reflect {
- private final Object mTargetObject;
-
- private Reflect(Object targetObject) {
- this.mTargetObject = targetObject;
- }
-
- /** Creates an instance of this helper to invoke methods on the given target object. */
- public static Reflect on(Object targetObject) {
- return new Reflect(targetObject);
- }
-
- /** Finds a method with the given name and parameter types. */
- public ReflectionMethod withMethod(String methodName, Class>... paramTypes)
- throws ReflectionException {
- try {
- return new ReflectionMethod(mTargetObject.getClass().getMethod(methodName, paramTypes));
- } catch (NoSuchMethodException e) {
- throw new ReflectionException(e);
- }
- }
-
- /** Represents an invokable method found reflectively. */
- public final class ReflectionMethod {
- private final Method mMethod;
-
- private ReflectionMethod(Method method) {
- this.mMethod = method;
- }
-
- /**
- * Invokes this instance method with the given parameters. The called method does not return
- * a value.
- */
- public void invoke(Object... parameters) throws ReflectionException {
- try {
- mMethod.invoke(mTargetObject, parameters);
- } catch (IllegalAccessException e) {
- throw new ReflectionException(e);
- } catch (InvocationTargetException e) {
- throw new ReflectionException(e);
- }
- }
-
- /**
- * Invokes this instance method with the given parameters. The called method returns a non
- * null value.
- */
- public Object get(Object... parameters) throws ReflectionException {
- Object value;
- try {
- value = mMethod.invoke(mTargetObject, parameters);
- } catch (IllegalAccessException e) {
- throw new ReflectionException(e);
- } catch (InvocationTargetException e) {
- throw new ReflectionException(e);
- }
- if (value == null) {
- throw new ReflectionException(new NullPointerException());
- }
- return value;
- }
- }
-}
diff --git a/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/ReflectionException.java b/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/ReflectionException.java
deleted file mode 100644
index 1c20c550a425751f530d6038dd57d85f66ce9f40..0000000000000000000000000000000000000000
--- a/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/ReflectionException.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.nearby.common.bluetooth.fastpair;
-
-/**
- * An exception thrown during a reflection operation. Like ReflectiveOperationException, except
- * compatible on older API versions.
- */
-public final class ReflectionException extends Exception {
- ReflectionException(Throwable cause) {
- super(cause.getMessage(), cause);
- }
-}
diff --git a/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/SignalLostException.java b/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/SignalLostException.java
deleted file mode 100644
index 244ee6642346b70bf814cbb8b608f1eb1790ed6f..0000000000000000000000000000000000000000
--- a/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/SignalLostException.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.nearby.common.bluetooth.fastpair;
-
-/** Base class for fast pair signal lost exceptions. */
-public class SignalLostException extends PairingException {
- SignalLostException(String message, Exception e) {
- super(message);
- initCause(e);
- }
-}
diff --git a/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/SignalRotatedException.java b/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/SignalRotatedException.java
deleted file mode 100644
index d0d2a5d636fab799807b5b619dbfd8d04075158f..0000000000000000000000000000000000000000
--- a/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/SignalRotatedException.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.nearby.common.bluetooth.fastpair;
-
-/** Base class for fast pair signal rotated exceptions. */
-public class SignalRotatedException extends PairingException {
- private final String mNewAddress;
-
- SignalRotatedException(String message, String newAddress, Exception e) {
- super(message);
- this.mNewAddress = newAddress;
- initCause(e);
- }
-
- /** Returns the new BLE address for the model ID. */
- public String getNewAddress() {
- return mNewAddress;
- }
-}
diff --git a/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/SimpleBroadcastReceiver.java b/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/SimpleBroadcastReceiver.java
deleted file mode 100644
index 7f525a7b313cc3f117548bb523b0b95887f4ea63..0000000000000000000000000000000000000000
--- a/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/SimpleBroadcastReceiver.java
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.nearby.common.bluetooth.fastpair;
-
-import android.annotation.TargetApi;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.os.Build.VERSION_CODES;
-import android.os.Handler;
-import android.util.Log;
-
-import androidx.annotation.Nullable;
-
-import com.google.common.util.concurrent.SettableFuture;
-
-import java.util.Arrays;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
-
-/**
- * Like {@link BroadcastReceiver}, but:
- *
- *
- *
Simpler to create and register, with a list of actions.
- *
Implements AutoCloseable. If used as a resource in try-with-resources (available on
- * KitKat+), unregisters itself automatically.
- *
Lets you block waiting for your state transition with {@link #await}.
- *
- */
-// AutoCloseable only available on KitKat+.
-@TargetApi(VERSION_CODES.KITKAT)
-public abstract class SimpleBroadcastReceiver extends BroadcastReceiver implements AutoCloseable {
-
- private static final String TAG = SimpleBroadcastReceiver.class.getSimpleName();
-
- /**
- * Creates a one shot receiver.
- */
- public static SimpleBroadcastReceiver oneShotReceiver(
- Context context, Preferences preferences, String... actions) {
- return new SimpleBroadcastReceiver(context, preferences, actions) {
- @Override
- protected void onReceive(Intent intent) {
- close();
- }
- };
- }
-
- private final Context mContext;
- private final SettableFuture mIsClosedFuture = SettableFuture.create();
- private long mAwaitExtendSecond;
-
- // Nullness checker complains about 'this' being @UnderInitialization
- @SuppressWarnings("nullness")
- public SimpleBroadcastReceiver(
- Context context, Preferences preferences, @Nullable Handler handler,
- String... actions) {
- Log.v(TAG, this + " listening for actions " + Arrays.toString(actions));
- this.mContext = context;
- IntentFilter intentFilter = new IntentFilter();
- if (preferences.getIncreaseIntentFilterPriority()) {
- intentFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
- }
- for (String action : actions) {
- intentFilter.addAction(action);
- }
- context.registerReceiver(this, intentFilter, /* broadcastPermission= */ null, handler);
- }
-
- public SimpleBroadcastReceiver(Context context, Preferences preferences, String... actions) {
- this(context, preferences, /* handler= */ null, actions);
- }
-
- /**
- * Any exception thrown by this method will be delivered via {@link #await}.
- */
- protected abstract void onReceive(Intent intent) throws Exception;
-
- @Override
- public void onReceive(Context context, Intent intent) {
- Log.v(TAG, "Got intent with action= " + intent.getAction());
- try {
- onReceive(intent);
- } catch (Exception e) {
- closeWithError(e);
- }
- }
-
- @Override
- public void close() {
- closeWithError(null);
- }
-
- void closeWithError(@Nullable Exception e) {
- try {
- mContext.unregisterReceiver(this);
- } catch (IllegalArgumentException ignored) {
- // Ignore. Happens if you unregister twice.
- }
- if (e == null) {
- mIsClosedFuture.set(null);
- } else {
- mIsClosedFuture.setException(e);
- }
- }
-
- /**
- * Extends the awaiting time.
- */
- public void extendAwaitSecond(int awaitExtendSecond) {
- this.mAwaitExtendSecond = awaitExtendSecond;
- }
-
- /**
- * Blocks until this receiver has closed (i.e. the state transition that this receiver is
- * interested in has completed). Throws an exception on any error.
- */
- public void await(long timeout, TimeUnit timeUnit)
- throws InterruptedException, ExecutionException, TimeoutException {
- Log.v(TAG, this + " waiting on future for " + timeout + " " + timeUnit);
- try {
- mIsClosedFuture.get(timeout, timeUnit);
- } catch (TimeoutException e) {
- if (mAwaitExtendSecond <= 0) {
- throw e;
- }
- Log.i(TAG, "Extend timeout for " + mAwaitExtendSecond + " seconds");
- mIsClosedFuture.get(mAwaitExtendSecond, TimeUnit.SECONDS);
- }
- }
-}
diff --git a/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/TdsException.java b/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/TdsException.java
deleted file mode 100644
index 7382ff371e4adfc92009122934e56cd300dfd3e2..0000000000000000000000000000000000000000
--- a/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/TdsException.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.nearby.common.bluetooth.fastpair;
-
-import com.android.server.nearby.intdefs.FastPairEventIntDefs.BrEdrHandoverErrorCode;
-
-import com.google.errorprone.annotations.FormatMethod;
-
-/**
- * Thrown when BR/EDR Handover fails.
- */
-public class TdsException extends Exception {
-
- final @BrEdrHandoverErrorCode int mErrorCode;
-
- @FormatMethod
- TdsException(@BrEdrHandoverErrorCode int errorCode, String format, Object... objects) {
- super(String.format(format, objects));
- this.mErrorCode = errorCode;
- }
-
- /** Returns error code. */
- public @BrEdrHandoverErrorCode int getErrorCode() {
- return mErrorCode;
- }
-}
-
diff --git a/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/TimingLogger.java b/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/TimingLogger.java
deleted file mode 100644
index 83ee3090267bf511d7ca7bf804a1a3019a442e1f..0000000000000000000000000000000000000000
--- a/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/TimingLogger.java
+++ /dev/null
@@ -1,237 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.nearby.common.bluetooth.fastpair;
-
-import android.os.SystemClock;
-import android.util.Log;
-
-import androidx.annotation.VisibleForTesting;
-
-import java.util.ArrayDeque;
-import java.util.List;
-import java.util.concurrent.CopyOnWriteArrayList;
-
-/**
- * A profiler for performance metrics.
- *
- *
This class aim to break down the execution time for each steps of process to figure out the
- * bottleneck.
- */
-public class TimingLogger {
-
- private static final String TAG = TimingLogger.class.getSimpleName();
-
- /**
- * The name of this session.
- */
- private final String mName;
-
- private final Preferences mPreference;
-
- /**
- * The ordered timing sequence data. It's composed by a paired {@link Timing} generated from
- * {@link #start} and {@link #end}.
- */
- private final List mTimings;
-
- private final long mStartTimestampMs;
-
- /** Constructor. */
- public TimingLogger(String name, Preferences mPreference) {
- this.mName = name;
- this.mPreference = mPreference;
- mTimings = new CopyOnWriteArrayList<>();
- mStartTimestampMs = SystemClock.elapsedRealtime();
- }
-
- @VisibleForTesting
- List getTimings() {
- return mTimings;
- }
-
- /**
- * Start a new paired timing.
- *
- * @param label The split name of paired timing.
- */
- public void start(String label) {
- if (mPreference.getEvaluatePerformance()) {
- mTimings.add(new Timing(label));
- }
- }
-
- /**
- * End a paired timing.
- */
- public void end() {
- if (mPreference.getEvaluatePerformance()) {
- mTimings.add(new Timing(Timing.END_LABEL));
- }
- }
-
- /**
- * Print out the timing data.
- */
- public void dump() {
- if (!mPreference.getEvaluatePerformance()) {
- return;
- }
-
- calculateTiming();
- Log.i(TAG, mName + "[Exclusive time] / [Total time] ([Timestamp])");
- int indentCount = 0;
- for (Timing timing : mTimings) {
- if (timing.isEndTiming()) {
- indentCount--;
- continue;
- }
- indentCount++;
- if (timing.mExclusiveTime == timing.mTotalTime) {
- Log.i(TAG, getIndentString(indentCount) + timing.mName + " " + timing.mExclusiveTime
- + "ms (" + getRelativeTimestamp(timing.getTimestamp()) + ")");
- } else {
- Log.i(TAG, getIndentString(indentCount) + timing.mName + " " + timing.mExclusiveTime
- + "ms / " + timing.mTotalTime + "ms (" + getRelativeTimestamp(
- timing.getTimestamp()) + ")");
- }
- }
- Log.i(TAG, mName + "end, " + getTotalTime() + "ms");
- }
-
- private void calculateTiming() {
- ArrayDeque arrayDeque = new ArrayDeque<>();
- for (Timing timing : mTimings) {
- if (timing.isStartTiming()) {
- arrayDeque.addFirst(timing);
- continue;
- }
-
- Timing timingStart = arrayDeque.removeFirst();
- final long time = timing.mTimestamp - timingStart.mTimestamp;
- timingStart.mExclusiveTime += time;
- timingStart.mTotalTime += time;
- if (!arrayDeque.isEmpty()) {
- arrayDeque.peekFirst().mExclusiveTime -= time;
- }
- }
- }
-
- private String getIndentString(int indentCount) {
- StringBuilder sb = new StringBuilder();
- for (int i = 0; i < indentCount; i++) {
- sb.append(" ");
- }
- return sb.toString();
- }
-
- private long getRelativeTimestamp(long timestamp) {
- return timestamp - mTimings.get(0).mTimestamp;
- }
-
- @VisibleForTesting
- long getTotalTime() {
- return mTimings.get(mTimings.size() - 1).mTimestamp - mTimings.get(0).mTimestamp;
- }
-
- /**
- * Gets the current latency since this object was created.
- */
- public long getLatencyMs() {
- return SystemClock.elapsedRealtime() - mStartTimestampMs;
- }
-
- @VisibleForTesting
- static class Timing {
-
- private static final String END_LABEL = "END_LABEL";
-
- /**
- * The name of this paired timing.
- */
- private final String mName;
-
- /**
- * System uptime in millisecond.
- */
- private final long mTimestamp;
-
- /**
- * The execution time exclude inner split timings.
- */
- private long mExclusiveTime;
-
- /**
- * The execution time within a start and an end timing.
- */
- private long mTotalTime;
-
- private Timing(String name) {
- this.mName = name;
- mTimestamp = SystemClock.elapsedRealtime();
- mExclusiveTime = 0;
- mTotalTime = 0;
- }
-
- @VisibleForTesting
- String getName() {
- return mName;
- }
-
- @VisibleForTesting
- long getTimestamp() {
- return mTimestamp;
- }
-
- @VisibleForTesting
- long getExclusiveTime() {
- return mExclusiveTime;
- }
-
- @VisibleForTesting
- long getTotalTime() {
- return mTotalTime;
- }
-
- @VisibleForTesting
- boolean isStartTiming() {
- return !isEndTiming();
- }
-
- @VisibleForTesting
- boolean isEndTiming() {
- return END_LABEL.equals(mName);
- }
- }
-
- /**
- * This class ensures each split timing is paired with a start and an end timing.
- */
- public static class ScopedTiming implements AutoCloseable {
-
- private final TimingLogger mTimingLogger;
-
- public ScopedTiming(TimingLogger logger, String label) {
- mTimingLogger = logger;
- mTimingLogger.start(label);
- }
-
- @Override
- public void close() {
- mTimingLogger.end();
- }
- }
-}
diff --git a/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/ToggleBluetoothTask.java b/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/ToggleBluetoothTask.java
deleted file mode 100644
index 41ac9f512fbee66ec2b01e89f227f9c509fc91d5..0000000000000000000000000000000000000000
--- a/nearby/service/java/com/android/server/nearby/common/bluetooth/fastpair/ToggleBluetoothTask.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.nearby.common.bluetooth.fastpair;
-
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeoutException;
-
-/** Task for toggling Bluetooth on and back off again. */
-interface ToggleBluetoothTask {
-
- /**
- * Toggles the bluetooth adapter off and back on again to help improve connection reliability.
- *
- * @throws InterruptedException when waiting for the bluetooth adapter's state to be set has
- * been interrupted.
- * @throws ExecutionException when waiting for the bluetooth adapter's state to be set has
- * failed.
- * @throws TimeoutException when the bluetooth adapter's state fails to be set on or off.
- */
- void toggleBluetooth() throws InterruptedException, ExecutionException, TimeoutException;
-}
diff --git a/nearby/service/java/com/android/server/nearby/common/bluetooth/gatt/BluetoothGattConnection.java b/nearby/service/java/com/android/server/nearby/common/bluetooth/gatt/BluetoothGattConnection.java
deleted file mode 100644
index de131e4ee6ce4579b3964b20f5c33113e47bd101..0000000000000000000000000000000000000000
--- a/nearby/service/java/com/android/server/nearby/common/bluetooth/gatt/BluetoothGattConnection.java
+++ /dev/null
@@ -1,781 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.nearby.common.bluetooth.gatt;
-
-import android.bluetooth.BluetoothGattCharacteristic;
-import android.bluetooth.BluetoothGattDescriptor;
-import android.bluetooth.BluetoothGattService;
-import android.bluetooth.BluetoothStatusCodes;
-import android.util.Log;
-
-import androidx.annotation.VisibleForTesting;
-
-import com.android.server.nearby.common.bluetooth.BluetoothConsts;
-import com.android.server.nearby.common.bluetooth.BluetoothException;
-import com.android.server.nearby.common.bluetooth.BluetoothGattException;
-import com.android.server.nearby.common.bluetooth.BluetoothTimeoutException;
-import com.android.server.nearby.common.bluetooth.ReservedUuids;
-import com.android.server.nearby.common.bluetooth.gatt.BluetoothGattHelper.ConnectionOptions;
-import com.android.server.nearby.common.bluetooth.gatt.BluetoothGattHelper.OperationType;
-import com.android.server.nearby.common.bluetooth.testability.android.bluetooth.BluetoothDevice;
-import com.android.server.nearby.common.bluetooth.testability.android.bluetooth.BluetoothGattWrapper;
-import com.android.server.nearby.common.bluetooth.util.BluetoothGattUtils;
-import com.android.server.nearby.common.bluetooth.util.BluetoothOperationExecutor;
-import com.android.server.nearby.common.bluetooth.util.BluetoothOperationExecutor.Operation;
-import com.android.server.nearby.common.bluetooth.util.BluetoothOperationExecutor.SynchronousOperation;
-
-import com.google.common.base.Preconditions;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.UUID;
-import java.util.concurrent.BlockingDeque;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-import java.util.concurrent.LinkedBlockingDeque;
-import java.util.concurrent.TimeUnit;
-
-import javax.annotation.Nullable;
-import javax.annotation.concurrent.GuardedBy;
-
-/**
- * Gatt connection to a Bluetooth device.
- */
-public class BluetoothGattConnection implements AutoCloseable {
-
- private static final String TAG = BluetoothGattConnection.class.getSimpleName();
-
- @VisibleForTesting
- static final long OPERATION_TIMEOUT_MILLIS = TimeUnit.SECONDS.toMillis(1);
- @VisibleForTesting
- static final long SLOW_OPERATION_TIMEOUT_MILLIS = TimeUnit.SECONDS.toMillis(10);
-
- @VisibleForTesting
- static final int GATT_INTERNAL_ERROR = 129;
- @VisibleForTesting
- static final int GATT_ERROR = 133;
-
- private final BluetoothGattWrapper mGatt;
- private final BluetoothOperationExecutor mBluetoothOperationExecutor;
- private final ConnectionOptions mConnectionOptions;
-
- private volatile boolean mServicesDiscovered = false;
-
- private volatile boolean mIsConnected = false;
-
- private volatile int mMtu = BluetoothConsts.DEFAULT_MTU;
-
- private final ConcurrentMap mChangeObservers =
- new ConcurrentHashMap<>();
-
- private final List mCloseListeners = new ArrayList<>();
-
- private long mOperationTimeoutMillis = OPERATION_TIMEOUT_MILLIS;
-
- BluetoothGattConnection(
- BluetoothGattWrapper gatt,
- BluetoothOperationExecutor bluetoothOperationExecutor,
- ConnectionOptions connectionOptions) {
- mGatt = gatt;
- mBluetoothOperationExecutor = bluetoothOperationExecutor;
- mConnectionOptions = connectionOptions;
- }
-
- /**
- * Set operation timeout.
- */
- public void setOperationTimeout(long timeoutMillis) {
- Preconditions.checkArgument(timeoutMillis > 0, "invalid time out value");
- mOperationTimeoutMillis = timeoutMillis;
- }
-
- /**
- * Returns connected device.
- */
- public BluetoothDevice getDevice() {
- return mGatt.getDevice();
- }
-
- public ConnectionOptions getConnectionOptions() {
- return mConnectionOptions;
- }
-
- public boolean isConnected() {
- return mIsConnected;
- }
-
- /**
- * Get service.
- */
- public BluetoothGattService getService(UUID uuid) throws BluetoothException {
- Log.d(TAG, String.format("Getting service %s.", uuid));
- if (!mServicesDiscovered) {
- discoverServices();
- }
- BluetoothGattService match = null;
- for (BluetoothGattService service : mGatt.getServices()) {
- if (service.getUuid().equals(uuid)) {
- if (match != null) {
- throw new BluetoothException(
- String.format("More than one service %s found on device %s.",
- uuid,
- mGatt.getDevice()));
- }
- match = service;
- }
- }
- if (match == null) {
- throw new BluetoothException(String.format("Service %s not found on device %s.",
- uuid,
- mGatt.getDevice()));
- }
- Log.d(TAG, "Service found.");
- return match;
- }
-
- /**
- * Returns a list of all characteristics under a given service UUID.
- */
- private List getCharacteristics(UUID serviceUuid)
- throws BluetoothException {
- if (!mServicesDiscovered) {
- discoverServices();
- }
- ArrayList characteristics = new ArrayList<>();
- for (BluetoothGattService service : mGatt.getServices()) {
- // Add all characteristics under this service if its service UUID matches.
- if (service.getUuid().equals(serviceUuid)) {
- characteristics.addAll(service.getCharacteristics());
- }
- }
- return characteristics;
- }
-
- /**
- * Get characteristic.
- */
- public BluetoothGattCharacteristic getCharacteristic(UUID serviceUuid,
- UUID characteristicUuid) throws BluetoothException {
- Log.d(TAG, String.format("Getting characteristic %s on service %s.", characteristicUuid,
- serviceUuid));
- BluetoothGattCharacteristic match = null;
- for (BluetoothGattCharacteristic characteristic : getCharacteristics(serviceUuid)) {
- if (characteristic.getUuid().equals(characteristicUuid)) {
- if (match != null) {
- throw new BluetoothException(String.format(
- "More than one characteristic %s found on service %s on device %s.",
- characteristicUuid,
- serviceUuid,
- mGatt.getDevice()));
- }
- match = characteristic;
- }
- }
- if (match == null) {
- throw new BluetoothException(String.format(
- "Characteristic %s not found on service %s of device %s.",
- characteristicUuid,
- serviceUuid,
- mGatt.getDevice()));
- }
- Log.d(TAG, "Characteristic found.");
- return match;
- }
-
- /**
- * Get descriptor.
- */
- public BluetoothGattDescriptor getDescriptor(UUID serviceUuid,
- UUID characteristicUuid, UUID descriptorUuid) throws BluetoothException {
- Log.d(TAG, String.format("Getting descriptor %s on characteristic %s on service %s.",
- descriptorUuid, characteristicUuid, serviceUuid));
- BluetoothGattDescriptor match = null;
- for (BluetoothGattDescriptor descriptor :
- getCharacteristic(serviceUuid, characteristicUuid).getDescriptors()) {
- if (descriptor.getUuid().equals(descriptorUuid)) {
- if (match != null) {
- throw new BluetoothException(String.format("More than one descriptor %s found "
- + "on characteristic %s service %s on device %s.",
- descriptorUuid,
- characteristicUuid,
- serviceUuid,
- mGatt.getDevice()));
- }
- match = descriptor;
- }
- }
- if (match == null) {
- throw new BluetoothException(String.format(
- "Descriptor %s not found on characteristic %s on service %s of device %s.",
- descriptorUuid,
- characteristicUuid,
- serviceUuid,
- mGatt.getDevice()));
- }
- Log.d(TAG, "Descriptor found.");
- return match;
- }
-
- /**
- * Discover services.
- */
- public void discoverServices() throws BluetoothException {
- mBluetoothOperationExecutor.execute(
- new SynchronousOperation(OperationType.DISCOVER_SERVICES) {
- @Nullable
- @Override
- public Void call() throws BluetoothException {
- if (mServicesDiscovered) {
- return null;
- }
- boolean forceRefresh = false;
- try {
- discoverServicesInternal();
- } catch (BluetoothException e) {
- if (!(e instanceof BluetoothGattException)) {
- throw e;
- }
- int errorCode = ((BluetoothGattException) e).getGattErrorCode();
- if (errorCode != GATT_ERROR && errorCode != GATT_INTERNAL_ERROR) {
- throw e;
- }
- Log.e(TAG, e.getMessage()
- + "\n Ignore the gatt error for post MNC apis and force "
- + "a refresh");
- forceRefresh = true;
- }
-
- forceRefreshServiceCacheIfNeeded(forceRefresh);
-
- mServicesDiscovered = true;
-
- return null;
- }
- });
- }
-
- private void discoverServicesInternal() throws BluetoothException {
- Log.i(TAG, "Starting services discovery.");
- long startTimeMillis = System.currentTimeMillis();
- try {
- mBluetoothOperationExecutor.execute(
- new Operation(OperationType.DISCOVER_SERVICES_INTERNAL, mGatt) {
- @Override
- public void run() throws BluetoothException {
- boolean success = mGatt.discoverServices();
- if (!success) {
- throw new BluetoothException(
- "gatt.discoverServices returned false.");
- }
- }
- },
- SLOW_OPERATION_TIMEOUT_MILLIS);
- Log.i(TAG, String.format("Services discovered successfully in %s ms.",
- System.currentTimeMillis() - startTimeMillis));
- } catch (BluetoothException e) {
- if (e instanceof BluetoothGattException) {
- throw new BluetoothGattException(String.format(
- "Failed to discover services on device: %s.",
- mGatt.getDevice()), ((BluetoothGattException) e).getGattErrorCode(), e);
- } else {
- throw new BluetoothException(String.format(
- "Failed to discover services on device: %s.",
- mGatt.getDevice()), e);
- }
- }
- }
-
- private boolean hasDynamicServices() {
- BluetoothGattService gattService =
- mGatt.getService(ReservedUuids.Services.GENERIC_ATTRIBUTE);
- if (gattService != null) {
- BluetoothGattCharacteristic serviceChange =
- gattService.getCharacteristic(ReservedUuids.Characteristics.SERVICE_CHANGE);
- if (serviceChange != null) {
- return true;
- }
- }
-
- // Check whether the server contains a self defined service dynamic characteristic.
- gattService = mGatt.getService(BluetoothConsts.SERVICE_DYNAMIC_SERVICE);
- if (gattService != null) {
- BluetoothGattCharacteristic serviceChange =
- gattService.getCharacteristic(BluetoothConsts.SERVICE_DYNAMIC_CHARACTERISTIC);
- if (serviceChange != null) {
- return true;
- }
- }
-
- return false;
- }
-
- private void forceRefreshServiceCacheIfNeeded(boolean forceRefresh) throws BluetoothException {
- if (mGatt.getDevice().getBondState() != BluetoothDevice.BOND_BONDED) {
- // Device is not bonded, so services should not have been cached.
- return;
- }
-
- if (!forceRefresh && !hasDynamicServices()) {
- return;
- }
- Log.i(TAG, "Forcing a refresh of local cache of GATT services");
- boolean success = mGatt.refresh();
- if (!success) {
- throw new BluetoothException("gatt.refresh returned false.");
- }
- discoverServicesInternal();
- }
-
- /**
- * Read characteristic.
- */
- public byte[] readCharacteristic(UUID serviceUuid, UUID characteristicUuid)
- throws BluetoothException {
- return readCharacteristic(getCharacteristic(serviceUuid, characteristicUuid));
- }
-
- /**
- * Read characteristic.
- */
- public byte[] readCharacteristic(final BluetoothGattCharacteristic characteristic)
- throws BluetoothException {
- try {
- return mBluetoothOperationExecutor.executeNonnull(
- new Operation(OperationType.READ_CHARACTERISTIC, mGatt,
- characteristic) {
- @Override
- public void run() throws BluetoothException {
- boolean success = mGatt.readCharacteristic(characteristic);
- if (!success) {
- throw new BluetoothException(
- "gatt.readCharacteristic returned false.");
- }
- }
- },
- mOperationTimeoutMillis);
- } catch (BluetoothException e) {
- throw new BluetoothException(String.format(
- "Failed to read %s on device %s.",
- BluetoothGattUtils.toString(characteristic),
- mGatt.getDevice()), e);
- }
- }
-
- /**
- * Writes Characteristic.
- */
- public void writeCharacteristic(UUID serviceUuid, UUID characteristicUuid, byte[] value)
- throws BluetoothException {
- writeCharacteristic(getCharacteristic(serviceUuid, characteristicUuid), value);
- }
-
- /**
- * Writes Characteristic.
- */
- public void writeCharacteristic(final BluetoothGattCharacteristic characteristic,
- final byte[] value) throws BluetoothException {
- Log.d(TAG, String.format("Writing %d bytes on %s on device %s.",
- value.length,
- BluetoothGattUtils.toString(characteristic),
- mGatt.getDevice()));
- if ((characteristic.getProperties() & (BluetoothGattCharacteristic.PROPERTY_WRITE
- | BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE)) == 0) {
- throw new BluetoothException(String.format("%s is not writable!", characteristic));
- }
- try {
- mBluetoothOperationExecutor.execute(
- new Operation(OperationType.WRITE_CHARACTERISTIC, mGatt, characteristic) {
- @Override
- public void run() throws BluetoothException {
- int writeCharacteristicResponseCode = mGatt.writeCharacteristic(
- characteristic, value, characteristic.getWriteType());
- if (writeCharacteristicResponseCode != BluetoothStatusCodes.SUCCESS) {
- throw new BluetoothException(
- "gatt.writeCharacteristic returned "
- + writeCharacteristicResponseCode);
- }
- }
- },
- mOperationTimeoutMillis);
- } catch (BluetoothException e) {
- throw new BluetoothException(String.format(
- "Failed to write %s on device %s.",
- BluetoothGattUtils.toString(characteristic),
- mGatt.getDevice()), e);
- }
- Log.d(TAG, "Writing characteristic done.");
- }
-
- /**
- * Reads descriptor.
- */
- public byte[] readDescriptor(UUID serviceUuid, UUID characteristicUuid, UUID descriptorUuid)
- throws BluetoothException {
- return readDescriptor(getDescriptor(serviceUuid, characteristicUuid, descriptorUuid));
- }
-
- /**
- * Reads descriptor.
- */
- public byte[] readDescriptor(final BluetoothGattDescriptor descriptor)
- throws BluetoothException {
- try {
- return mBluetoothOperationExecutor.executeNonnull(
- new Operation(OperationType.READ_DESCRIPTOR, mGatt, descriptor) {
- @Override
- public void run() throws BluetoothException {
- boolean success = mGatt.readDescriptor(descriptor);
- if (!success) {
- throw new BluetoothException("gatt.readDescriptor returned false.");
- }
- }
- },
- mOperationTimeoutMillis);
- } catch (BluetoothException e) {
- throw new BluetoothException(String.format(
- "Failed to read %s on %s on device %s.",
- descriptor.getUuid(),
- BluetoothGattUtils.toString(descriptor),
- mGatt.getDevice()), e);
- }
- }
-
- /**
- * Writes descriptor.
- */
- public void writeDescriptor(UUID serviceUuid, UUID characteristicUuid, UUID descriptorUuid,
- byte[] value) throws BluetoothException {
- writeDescriptor(getDescriptor(serviceUuid, characteristicUuid, descriptorUuid), value);
- }
-
- /**
- * Writes descriptor.
- */
- public void writeDescriptor(final BluetoothGattDescriptor descriptor, final byte[] value)
- throws BluetoothException {
- Log.d(TAG, String.format(
- "Writing %d bytes on %s on device %s.",
- value.length,
- BluetoothGattUtils.toString(descriptor),
- mGatt.getDevice()));
- long startTimeMillis = System.currentTimeMillis();
- try {
- mBluetoothOperationExecutor.execute(
- new Operation(OperationType.WRITE_DESCRIPTOR, mGatt, descriptor) {
- @Override
- public void run() throws BluetoothException {
- int writeDescriptorResponseCode = mGatt.writeDescriptor(descriptor,
- value);
- if (writeDescriptorResponseCode != BluetoothStatusCodes.SUCCESS) {
- throw new BluetoothException(
- "gatt.writeDescriptor returned "
- + writeDescriptorResponseCode);
- }
- }
- },
- mOperationTimeoutMillis);
- Log.d(TAG, String.format("Writing descriptor done in %s ms.",
- System.currentTimeMillis() - startTimeMillis));
- } catch (BluetoothException e) {
- throw new BluetoothException(String.format(
- "Failed to write %s on device %s.",
- BluetoothGattUtils.toString(descriptor),
- mGatt.getDevice()), e);
- }
- }
-
- /**
- * Reads remote Rssi.
- */
- public int readRemoteRssi() throws BluetoothException {
- try {
- return mBluetoothOperationExecutor.executeNonnull(
- new Operation(OperationType.READ_RSSI, mGatt) {
- @Override
- public void run() throws BluetoothException {
- boolean success = mGatt.readRemoteRssi();
- if (!success) {
- throw new BluetoothException("gatt.readRemoteRssi returned false.");
- }
- }
- },
- mOperationTimeoutMillis);
- } catch (BluetoothException e) {
- throw new BluetoothException(
- String.format("Failed to read rssi on device %s.", mGatt.getDevice()), e);
- }
- }
-
- public int getMtu() {
- return mMtu;
- }
-
- /**
- * Get max data packet size.
- */
- public int getMaxDataPacketSize() {
- // Per BT specs (3.2.9), only MTU - 3 bytes can be used to transmit data
- return mMtu - 3;
- }
-
- /** Set notification enabled or disabled. */
- @VisibleForTesting
- public void setNotificationEnabled(BluetoothGattCharacteristic characteristic, boolean enabled)
- throws BluetoothException {
- boolean isIndication;
- int properties = characteristic.getProperties();
- if ((properties & BluetoothGattCharacteristic.PROPERTY_NOTIFY) != 0) {
- isIndication = false;
- } else if ((properties & BluetoothGattCharacteristic.PROPERTY_INDICATE) != 0) {
- isIndication = true;
- } else {
- throw new BluetoothException(String.format(
- "%s on device %s supports neither notifications nor indications.",
- BluetoothGattUtils.toString(characteristic),
- mGatt.getDevice()));
- }
- BluetoothGattDescriptor clientConfigDescriptor =
- characteristic.getDescriptor(
- ReservedUuids.Descriptors.CLIENT_CHARACTERISTIC_CONFIGURATION);
- if (clientConfigDescriptor == null) {
- throw new BluetoothException(String.format(
- "%s on device %s is missing client config descriptor.",
- BluetoothGattUtils.toString(characteristic),
- mGatt.getDevice()));
- }
- long startTime = System.currentTimeMillis();
- Log.d(TAG, String.format("%s %s on characteristic %s.", enabled ? "Enabling" : "Disabling",
- isIndication ? "indication" : "notification", characteristic.getUuid()));
-
- if (enabled) {
- mGatt.setCharacteristicNotification(characteristic, enabled);
- }
- writeDescriptor(clientConfigDescriptor,
- enabled
- ? (isIndication
- ? BluetoothGattDescriptor.ENABLE_INDICATION_VALUE :
- BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE)
- : BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE);
- if (!enabled) {
- mGatt.setCharacteristicNotification(characteristic, enabled);
- }
-
- Log.d(TAG, String.format("Done in %d ms.", System.currentTimeMillis() - startTime));
- }
-
- /**
- * Enables notification.
- */
- public ChangeObserver enableNotification(UUID serviceUuid, UUID characteristicUuid)
- throws BluetoothException {
- return enableNotification(getCharacteristic(serviceUuid, characteristicUuid));
- }
-
- /**
- * Enables notification.
- */
- public ChangeObserver enableNotification(final BluetoothGattCharacteristic characteristic)
- throws BluetoothException {
- return mBluetoothOperationExecutor.executeNonnull(
- new SynchronousOperation(
- OperationType.NOTIFICATION_CHANGE,
- characteristic) {
- @Override
- public ChangeObserver call() throws BluetoothException {
- ChangeObserver changeObserver = new ChangeObserver();
- mChangeObservers.put(characteristic, changeObserver);
- setNotificationEnabled(characteristic, true);
- return changeObserver;
- }
- });
- }
-
- /**
- * Disables notification.
- */
- public void disableNotification(UUID serviceUuid, UUID characteristicUuid)
- throws BluetoothException {
- disableNotification(getCharacteristic(serviceUuid, characteristicUuid));
- }
-
- /**
- * Disables notification.
- */
- public void disableNotification(final BluetoothGattCharacteristic characteristic)
- throws BluetoothException {
- mBluetoothOperationExecutor.execute(
- new SynchronousOperation(
- OperationType.NOTIFICATION_CHANGE,
- characteristic) {
- @Nullable
- @Override
- public Void call() throws BluetoothException {
- setNotificationEnabled(characteristic, false);
- mChangeObservers.remove(characteristic);
- return null;
- }
- });
- }
-
- /**
- * Adds a close listener.
- */
- public void addCloseListener(ConnectionCloseListener listener) {
- mCloseListeners.add(listener);
- if (!mIsConnected) {
- listener.onClose();
- return;
- }
- }
-
- /**
- * Removes a close listener.
- */
- public void removeCloseListener(ConnectionCloseListener listener) {
- mCloseListeners.remove(listener);
- }
-
- /** onCharacteristicChanged callback. */
- public void onCharacteristicChanged(BluetoothGattCharacteristic characteristic, byte[] value) {
- ChangeObserver observer = mChangeObservers.get(characteristic);
- if (observer == null) {
- return;
- }
- observer.onValueChange(value);
- }
-
- @Override
- public void close() throws BluetoothException {
- Log.d(TAG, "close");
- try {
- if (!mIsConnected) {
- // Don't call disconnect on a closed connection, since Android framework won't
- // provide any feedback.
- return;
- }
- mBluetoothOperationExecutor.execute(
- new Operation(OperationType.DISCONNECT, mGatt.getDevice()) {
- @Override
- public void run() throws BluetoothException {
- mGatt.disconnect();
- }
- }, mOperationTimeoutMillis);
- } finally {
- mGatt.close();
- }
- }
-
- /** onConnected callback. */
- public void onConnected() {
- Log.d(TAG, "onConnected");
- mIsConnected = true;
- }
-
- /** onClosed callback. */
- public void onClosed() {
- Log.d(TAG, "onClosed");
- if (!mIsConnected) {
- return;
- }
- mIsConnected = false;
- for (ConnectionCloseListener listener : mCloseListeners) {
- listener.onClose();
- }
- mGatt.close();
- }
-
- /**
- * Observer to wait or be called back when value change.
- */
- public static class ChangeObserver {
-
- private final BlockingDeque mValues = new LinkedBlockingDeque();
-
- @GuardedBy("mValues")
- @Nullable
- private volatile CharacteristicChangeListener mListener;
-
- /**
- * Set listener.
- */
- public void setListener(@Nullable CharacteristicChangeListener listener) {
- synchronized (mValues) {
- mListener = listener;
- if (listener != null) {
- byte[] value;
- while ((value = mValues.poll()) != null) {
- listener.onValueChange(value);
- }
- }
- }
- }
-
- /**
- * onValueChange callback.
- */
- public void onValueChange(byte[] newValue) {
- synchronized (mValues) {
- CharacteristicChangeListener listener = mListener;
- if (listener == null) {
- mValues.add(newValue);
- } else {
- listener.onValueChange(newValue);
- }
- }
- }
-
- /**
- * Waits for update for a given time.
- */
- public byte[] waitForUpdate(long timeoutMillis) throws BluetoothException {
- byte[] result;
- try {
- result = mValues.poll(timeoutMillis, TimeUnit.MILLISECONDS);
- } catch (InterruptedException e) {
- Thread.currentThread().interrupt();
- throw new BluetoothException("Operation interrupted.");
- }
- if (result == null) {
- throw new BluetoothTimeoutException(
- String.format("Operation timed out after %dms", timeoutMillis));
- }
- return result;
- }
- }
-
- /**
- * Listener for characteristic data changes over notifications or indications.
- */
- public interface CharacteristicChangeListener {
-
- /**
- * onValueChange callback.
- */
- void onValueChange(byte[] newValue);
- }
-
- /**
- * Listener for connection close events.
- */
- public interface ConnectionCloseListener {
-
- /**
- * onClose callback.
- */
- void onClose();
- }
-}
diff --git a/nearby/service/java/com/android/server/nearby/common/bluetooth/gatt/BluetoothGattHelper.java b/nearby/service/java/com/android/server/nearby/common/bluetooth/gatt/BluetoothGattHelper.java
deleted file mode 100644
index 18a9f5f3bbbef35ee98e34e9ab50f2693c4ed9ea..0000000000000000000000000000000000000000
--- a/nearby/service/java/com/android/server/nearby/common/bluetooth/gatt/BluetoothGattHelper.java
+++ /dev/null
@@ -1,690 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.nearby.common.bluetooth.gatt;
-
-import android.bluetooth.BluetoothGatt;
-import android.bluetooth.BluetoothGattCharacteristic;
-import android.bluetooth.BluetoothGattDescriptor;
-import android.bluetooth.le.ScanFilter;
-import android.bluetooth.le.ScanSettings;
-import android.content.Context;
-import android.os.ParcelUuid;
-import android.util.Log;
-
-import androidx.annotation.IntDef;
-import androidx.annotation.VisibleForTesting;
-
-import com.android.server.nearby.common.bluetooth.BluetoothException;
-import com.android.server.nearby.common.bluetooth.testability.android.bluetooth.BluetoothAdapter;
-import com.android.server.nearby.common.bluetooth.testability.android.bluetooth.BluetoothDevice;
-import com.android.server.nearby.common.bluetooth.testability.android.bluetooth.BluetoothGattCallback;
-import com.android.server.nearby.common.bluetooth.testability.android.bluetooth.BluetoothGattWrapper;
-import com.android.server.nearby.common.bluetooth.testability.android.bluetooth.le.BluetoothLeScanner;
-import com.android.server.nearby.common.bluetooth.testability.android.bluetooth.le.ScanCallback;
-import com.android.server.nearby.common.bluetooth.testability.android.bluetooth.le.ScanResult;
-import com.android.server.nearby.common.bluetooth.util.BluetoothOperationExecutor;
-import com.android.server.nearby.common.bluetooth.util.BluetoothOperationExecutor.BluetoothOperationTimeoutException;
-import com.android.server.nearby.common.bluetooth.util.BluetoothOperationExecutor.Operation;
-
-import com.google.common.base.Preconditions;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.Arrays;
-import java.util.Locale;
-import java.util.Objects;
-import java.util.Optional;
-import java.util.UUID;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-import java.util.concurrent.TimeUnit;
-
-import javax.annotation.Nullable;
-import javax.annotation.concurrent.GuardedBy;
-
-/**
- * Wrapper of {@link BluetoothGattWrapper} that provides blocking methods, errors and timeout
- * handling.
- */
-@SuppressWarnings("Guava") // java.util.Optional is not available until API 24
-public class BluetoothGattHelper {
-
- private static final String TAG = BluetoothGattHelper.class.getSimpleName();
-
- @VisibleForTesting
- static final long LOW_LATENCY_SCAN_MILLIS = TimeUnit.SECONDS.toMillis(5);
- private static final long POLL_INTERVAL_MILLIS = 5L /* milliseconds */;
-
- /**
- * BT operation types that can be in flight.
- */
- @Retention(RetentionPolicy.SOURCE)
- @IntDef(
- value = {
- OperationType.SCAN,
- OperationType.CONNECT,
- OperationType.DISCOVER_SERVICES,
- OperationType.DISCOVER_SERVICES_INTERNAL,
- OperationType.NOTIFICATION_CHANGE,
- OperationType.READ_CHARACTERISTIC,
- OperationType.WRITE_CHARACTERISTIC,
- OperationType.READ_DESCRIPTOR,
- OperationType.WRITE_DESCRIPTOR,
- OperationType.READ_RSSI,
- OperationType.WRITE_RELIABLE,
- OperationType.CHANGE_MTU,
- OperationType.DISCONNECT,
- })
- public @interface OperationType {
- int SCAN = 0;
- int CONNECT = 1;
- int DISCOVER_SERVICES = 2;
- int DISCOVER_SERVICES_INTERNAL = 3;
- int NOTIFICATION_CHANGE = 4;
- int READ_CHARACTERISTIC = 5;
- int WRITE_CHARACTERISTIC = 6;
- int READ_DESCRIPTOR = 7;
- int WRITE_DESCRIPTOR = 8;
- int READ_RSSI = 9;
- int WRITE_RELIABLE = 10;
- int CHANGE_MTU = 11;
- int DISCONNECT = 12;
- }
-
- @VisibleForTesting
- final ScanCallback mScanCallback = new InternalScanCallback();
- @VisibleForTesting
- final BluetoothGattCallback mBluetoothGattCallback =
- new InternalBluetoothGattCallback();
- @VisibleForTesting
- final ConcurrentMap mConnections =
- new ConcurrentHashMap<>();
-
- private final Context mApplicationContext;
- private final BluetoothAdapter mBluetoothAdapter;
- private final BluetoothOperationExecutor mBluetoothOperationExecutor;
-
- @VisibleForTesting
- BluetoothGattHelper(
- Context applicationContext,
- BluetoothAdapter bluetoothAdapter,
- BluetoothOperationExecutor bluetoothOperationExecutor) {
- mApplicationContext = applicationContext;
- mBluetoothAdapter = bluetoothAdapter;
- mBluetoothOperationExecutor = bluetoothOperationExecutor;
- }
-
- public BluetoothGattHelper(Context applicationContext, BluetoothAdapter bluetoothAdapter) {
- this(
- Preconditions.checkNotNull(applicationContext),
- Preconditions.checkNotNull(bluetoothAdapter),
- new BluetoothOperationExecutor(5));
- }
-
- /**
- * Auto-connects a serice Uuid.
- */
- public BluetoothGattConnection autoConnect(final UUID serviceUuid) throws BluetoothException {
- Log.d(TAG, String.format("Starting autoconnection to a device advertising service %s.",
- serviceUuid));
- BluetoothDevice device = null;
- int retries = 3;
- final BluetoothLeScanner scanner = mBluetoothAdapter.getBluetoothLeScanner();
- if (scanner == null) {
- throw new BluetoothException("Bluetooth is disabled or LE is not supported.");
- }
- final ScanFilter serviceFilter = new ScanFilter.Builder()
- .setServiceUuid(new ParcelUuid(serviceUuid))
- .build();
- ScanSettings.Builder scanSettingsBuilder = new ScanSettings.Builder()
- .setReportDelay(0);
- final ScanSettings scanSettingsLowLatency = scanSettingsBuilder
- .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
- .build();
- final ScanSettings scanSettingsLowPower = scanSettingsBuilder
- .setScanMode(ScanSettings.SCAN_MODE_LOW_POWER)
- .build();
- while (true) {
- long startTimeMillis = System.currentTimeMillis();
- try {
- Log.d(TAG, "Starting low latency scanning.");
- device =
- mBluetoothOperationExecutor.executeNonnull(
- new Operation(OperationType.SCAN) {
- @Override
- public void run() throws BluetoothException {
- scanner.startScan(Arrays.asList(serviceFilter),
- scanSettingsLowLatency, mScanCallback);
- }
- }, LOW_LATENCY_SCAN_MILLIS);
- } catch (BluetoothOperationTimeoutException e) {
- Log.d(TAG, String.format(
- "Cannot find a nearby device in low latency scanning after %s ms.",
- LOW_LATENCY_SCAN_MILLIS));
- } finally {
- scanner.stopScan(mScanCallback);
- }
- if (device == null) {
- Log.d(TAG, "Starting low power scanning.");
- try {
- device = mBluetoothOperationExecutor.executeNonnull(
- new Operation(OperationType.SCAN) {
- @Override
- public void run() throws BluetoothException {
- scanner.startScan(Arrays.asList(serviceFilter),
- scanSettingsLowPower, mScanCallback);
- }
- });
- } finally {
- scanner.stopScan(mScanCallback);
- }
- }
- Log.d(TAG, String.format("Scanning done in %d ms. Found device %s.",
- System.currentTimeMillis() - startTimeMillis, device));
-
- try {
- return connect(device);
- } catch (BluetoothException e) {
- retries--;
- if (retries == 0) {
- throw e;
- } else {
- Log.d(TAG, String.format(
- "Connection failed: %s. Retrying %d more times.", e, retries));
- }
- }
- }
- }
-
- /**
- * Connects to a device using default connection options.
- */
- public BluetoothGattConnection connect(BluetoothDevice bluetoothDevice)
- throws BluetoothException {
- return connect(bluetoothDevice, ConnectionOptions.builder().build());
- }
-
- /**
- * Connects to a device using specifies connection options.
- */
- public BluetoothGattConnection connect(
- BluetoothDevice bluetoothDevice, ConnectionOptions options) throws BluetoothException {
- Log.d(TAG, String.format("Connecting to device %s.", bluetoothDevice));
- long startTimeMillis = System.currentTimeMillis();
-
- Operation connectOperation =
- new Operation(OperationType.CONNECT, bluetoothDevice) {
- private final Object mLock = new Object();
-
- @GuardedBy("mLock")
- private boolean mIsCanceled = false;
-
- @GuardedBy("mLock")
- @Nullable(/* null before operation is executed */)
- private BluetoothGattWrapper mBluetoothGatt;
-
- @Override
- public void run() throws BluetoothException {
- synchronized (mLock) {
- if (mIsCanceled) {
- return;
- }
- BluetoothGattWrapper bluetoothGattWrapper;
- Log.d(TAG, "Use LE transport");
- bluetoothGattWrapper =
- bluetoothDevice.connectGatt(
- mApplicationContext,
- options.autoConnect(),
- mBluetoothGattCallback,
- android.bluetooth.BluetoothDevice.TRANSPORT_LE);
- if (bluetoothGattWrapper == null) {
- throw new BluetoothException("connectGatt() returned null.");
- }
-
- try {
- // Set connection priority without waiting for connection callback.
- // Per code, btif_gatt_client.c, when priority is set before
- // connection, this sets preferred connection parameters that will
- // be used during the connection establishment.
- Optional connectionPriorityOption =
- options.connectionPriority();
- if (connectionPriorityOption.isPresent()) {
- // requestConnectionPriority can only be called when
- // BluetoothGatt is connected to the system BluetoothGatt
- // service (see android/bluetooth/BluetoothGatt.java code).
- // However, there is no callback to the app to inform when this
- // is done. requestConnectionPriority will returns false with no
- // side-effect before the service is connected, so we just poll
- // here until true is returned.
- int connectionPriority = connectionPriorityOption.get();
- long startTimeMillis = System.currentTimeMillis();
- while (!bluetoothGattWrapper.requestConnectionPriority(
- connectionPriority)) {
- if (System.currentTimeMillis() - startTimeMillis
- > options.connectionTimeoutMillis()) {
- throw new BluetoothException(
- String.format(
- Locale.US,
- "Failed to set connectionPriority "
- + "after %dms.",
- options.connectionTimeoutMillis()));
- }
- try {
- Thread.sleep(POLL_INTERVAL_MILLIS);
- } catch (InterruptedException e) {
- Thread.currentThread().interrupt();
- throw new BluetoothException(
- "connect() operation interrupted.");
- }
- }
- }
- } catch (Exception e) {
- // Make sure to clean connection.
- bluetoothGattWrapper.disconnect();
- bluetoothGattWrapper.close();
- throw e;
- }
-
- BluetoothGattConnection connection = new BluetoothGattConnection(
- bluetoothGattWrapper, mBluetoothOperationExecutor, options);
- mConnections.put(bluetoothGattWrapper, connection);
- mBluetoothGatt = bluetoothGattWrapper;
- }
- }
-
- @Override
- public void cancel() {
- // Clean connection if connection times out.
- synchronized (mLock) {
- if (mIsCanceled) {
- return;
- }
- mIsCanceled = true;
- BluetoothGattWrapper bluetoothGattWrapper = mBluetoothGatt;
- if (bluetoothGattWrapper == null) {
- return;
- }
- mConnections.remove(bluetoothGattWrapper);
- bluetoothGattWrapper.disconnect();
- bluetoothGattWrapper.close();
- }
- }
- };
- BluetoothGattConnection result;
- if (options.autoConnect()) {
- result = mBluetoothOperationExecutor.executeNonnull(connectOperation);
- } else {
- result =
- mBluetoothOperationExecutor.executeNonnull(
- connectOperation, options.connectionTimeoutMillis());
- }
- Log.d(TAG, String.format("Connection success in %d ms.",
- System.currentTimeMillis() - startTimeMillis));
- return result;
- }
-
- private BluetoothGattConnection getConnectionByGatt(BluetoothGattWrapper gatt)
- throws BluetoothException {
- BluetoothGattConnection connection = mConnections.get(gatt);
- if (connection == null) {
- throw new BluetoothException("Receive callback on unexpected device: " + gatt);
- }
- return connection;
- }
-
- private class InternalBluetoothGattCallback extends BluetoothGattCallback {
-
- @Override
- public void onConnectionStateChange(BluetoothGattWrapper gatt, int status, int newState) {
- BluetoothGattConnection connection;
- BluetoothDevice device = gatt.getDevice();
- switch (newState) {
- case BluetoothGatt.STATE_CONNECTED: {
- connection = mConnections.get(gatt);
- if (connection == null) {
- Log.w(TAG, String.format(
- "Received unexpected successful connection for dev %s! Ignoring.",
- device));
- break;
- }
-
- Operation operation =
- new Operation<>(OperationType.CONNECT, device);
- if (status != BluetoothGatt.GATT_SUCCESS) {
- mConnections.remove(gatt);
- gatt.disconnect();
- gatt.close();
- mBluetoothOperationExecutor.notifyCompletion(operation, status, null);
- break;
- }
-
- // Process connection options
- ConnectionOptions options = connection.getConnectionOptions();
- Optional mtuOption = options.mtu();
- if (mtuOption.isPresent()) {
- // Requesting MTU and waiting for MTU callback.
- boolean success = gatt.requestMtu(mtuOption.get());
- if (!success) {
- mBluetoothOperationExecutor.notifyFailure(operation,
- new BluetoothException(String.format(Locale.US,
- "Failed to request MTU of %d for dev %s: "
- + "returned false.",
- mtuOption.get(), device)));
- // Make sure to clean connection.
- mConnections.remove(gatt);
- gatt.disconnect();
- gatt.close();
- }
- break;
- }
-
- // Connection successful
- connection.onConnected();
- mBluetoothOperationExecutor.notifyCompletion(operation, status, connection);
- break;
- }
- case BluetoothGatt.STATE_DISCONNECTED: {
- connection = mConnections.remove(gatt);
- if (connection == null) {
- Log.w(TAG, String.format("Received unexpected disconnection"
- + " for device %s! Ignoring.", device));
- break;
- }
- if (!connection.isConnected()) {
- // This is a failed connection attempt
- if (status == BluetoothGatt.GATT_SUCCESS) {
- // This is weird... considering this as a failure
- Log.w(TAG, String.format(
- "Received a success for a failed connection "
- + "attempt for device %s! Ignoring.", device));
- status = BluetoothGatt.GATT_FAILURE;
- }
- mBluetoothOperationExecutor
- .notifyCompletion(new Operation(
- OperationType.CONNECT, device), status, null);
- // Clean Gatt object in every case.
- gatt.disconnect();
- gatt.close();
- break;
- }
- connection.onClosed();
- mBluetoothOperationExecutor.notifyCompletion(
- new Operation<>(OperationType.DISCONNECT, device), status);
- break;
- }
- default:
- Log.e(TAG, "Unexpected connection state: " + newState);
- }
- }
-
- @Override
- public void onMtuChanged(BluetoothGattWrapper gatt, int mtu, int status) {
- BluetoothGattConnection connection = mConnections.get(gatt);
- BluetoothDevice device = gatt.getDevice();
- if (connection == null) {
- Log.w(TAG, String.format(
- "Received unexpected MTU change for device %s! Ignoring.", device));
- return;
- }
- if (connection.isConnected()) {
- // This is the callback for the deprecated BluetoothGattConnection.requestMtu.
- mBluetoothOperationExecutor.notifyCompletion(
- new Operation<>(OperationType.CHANGE_MTU, gatt), status, mtu);
- } else {
- // This is the callback when requesting MTU right after connecting.
- connection.onConnected();
- mBluetoothOperationExecutor.notifyCompletion(
- new Operation<>(OperationType.CONNECT, device), status, connection);
- if (status != BluetoothGatt.GATT_SUCCESS) {
- Log.w(TAG, String.format(
- "%s responds MTU change failed, status %s.", device, status));
- // Clean connection if it's failed.
- mConnections.remove(gatt);
- gatt.disconnect();
- gatt.close();
- return;
- }
- }
- }
-
- @Override
- public void onServicesDiscovered(BluetoothGattWrapper gatt, int status) {
- mBluetoothOperationExecutor.notifyCompletion(
- new Operation(OperationType.DISCOVER_SERVICES_INTERNAL, gatt), status);
- }
-
- @Override
- public void onCharacteristicRead(BluetoothGattWrapper gatt,
- BluetoothGattCharacteristic characteristic, int status) {
- mBluetoothOperationExecutor.notifyCompletion(
- new Operation(OperationType.READ_CHARACTERISTIC, gatt, characteristic),
- status, characteristic.getValue());
- }
-
- @Override
- public void onCharacteristicWrite(BluetoothGattWrapper gatt,
- BluetoothGattCharacteristic characteristic, int status) {
- mBluetoothOperationExecutor.notifyCompletion(new Operation(
- OperationType.WRITE_CHARACTERISTIC, gatt, characteristic), status);
- }
-
- @Override
- public void onDescriptorRead(BluetoothGattWrapper gatt, BluetoothGattDescriptor descriptor,
- int status) {
- mBluetoothOperationExecutor.notifyCompletion(
- new Operation(OperationType.READ_DESCRIPTOR, gatt, descriptor), status,
- descriptor.getValue());
- }
-
- @Override
- public void onDescriptorWrite(BluetoothGattWrapper gatt, BluetoothGattDescriptor descriptor,
- int status) {
- Log.d(TAG, String.format("onDescriptorWrite %s, %s, %d",
- gatt.getDevice(), descriptor.getUuid(), status));
- mBluetoothOperationExecutor.notifyCompletion(
- new Operation(OperationType.WRITE_DESCRIPTOR, gatt, descriptor), status);
- }
-
- @Override
- public void onReadRemoteRssi(BluetoothGattWrapper gatt, int rssi, int status) {
- mBluetoothOperationExecutor.notifyCompletion(
- new Operation(OperationType.READ_RSSI, gatt), status, rssi);
- }
-
- @Override
- public void onReliableWriteCompleted(BluetoothGattWrapper gatt, int status) {
- mBluetoothOperationExecutor.notifyCompletion(
- new Operation(OperationType.WRITE_RELIABLE, gatt), status);
- }
-
- @Override
- public void onCharacteristicChanged(BluetoothGattWrapper gatt,
- BluetoothGattCharacteristic characteristic) {
- byte[] value = characteristic.getValue();
- if (value == null) {
- // Value is not supposed to be null, but just to be safe...
- value = new byte[0];
- }
- Log.d(TAG, String.format("Characteristic %s changed, Gatt device: %s",
- characteristic.getUuid(), gatt.getDevice()));
- try {
- getConnectionByGatt(gatt).onCharacteristicChanged(characteristic, value);
- } catch (BluetoothException e) {
- Log.e(TAG, "Error in onCharacteristicChanged", e);
- }
- }
- }
-
- private class InternalScanCallback extends ScanCallback {
-
- @Override
- public void onScanFailed(int errorCode) {
- String errorMessage;
- switch (errorCode) {
- case ScanCallback.SCAN_FAILED_ALREADY_STARTED:
- errorMessage = "SCAN_FAILED_ALREADY_STARTED";
- break;
- case ScanCallback.SCAN_FAILED_APPLICATION_REGISTRATION_FAILED:
- errorMessage = "SCAN_FAILED_APPLICATION_REGISTRATION_FAILED";
- break;
- case ScanCallback.SCAN_FAILED_FEATURE_UNSUPPORTED:
- errorMessage = "SCAN_FAILED_FEATURE_UNSUPPORTED";
- break;
- case ScanCallback.SCAN_FAILED_INTERNAL_ERROR:
- errorMessage = "SCAN_FAILED_INTERNAL_ERROR";
- break;
- default:
- errorMessage = "Unknown error code - " + errorCode;
- }
- mBluetoothOperationExecutor.notifyFailure(
- new Operation(OperationType.SCAN),
- new BluetoothException("Scan failed: " + errorMessage));
- }
-
- @Override
- public void onScanResult(int callbackType, ScanResult result) {
- mBluetoothOperationExecutor.notifySuccess(
- new Operation(OperationType.SCAN), result.getDevice());
- }
- }
-
- /**
- * Options for {@link #connect}.
- */
- public static class ConnectionOptions {
-
- private boolean mAutoConnect;
- private long mConnectionTimeoutMillis;
- private Optional mConnectionPriority;
- private Optional mMtu;
-
- private ConnectionOptions(boolean autoConnect, long connectionTimeoutMillis,
- Optional connectionPriority,
- Optional mtu) {
- this.mAutoConnect = autoConnect;
- this.mConnectionTimeoutMillis = connectionTimeoutMillis;
- this.mConnectionPriority = connectionPriority;
- this.mMtu = mtu;
- }
-
- boolean autoConnect() {
- return mAutoConnect;
- }
-
- long connectionTimeoutMillis() {
- return mConnectionTimeoutMillis;
- }
-
- Optional connectionPriority() {
- return mConnectionPriority;
- }
-
- Optional mtu() {
- return mMtu;
- }
-
- @Override
- public String toString() {
- return "ConnectionOptions{"
- + "autoConnect=" + mAutoConnect + ", "
- + "connectionTimeoutMillis=" + mConnectionTimeoutMillis + ", "
- + "connectionPriority=" + mConnectionPriority + ", "
- + "mtu=" + mMtu
- + "}";
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
- if (o instanceof ConnectionOptions) {
- ConnectionOptions that = (ConnectionOptions) o;
- return this.mAutoConnect == that.autoConnect()
- && this.mConnectionTimeoutMillis == that.connectionTimeoutMillis()
- && this.mConnectionPriority.equals(that.connectionPriority())
- && this.mMtu.equals(that.mtu());
- }
- return false;
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(mAutoConnect, mConnectionTimeoutMillis, mConnectionPriority, mMtu);
- }
-
- /**
- * Creates a builder of ConnectionOptions.
- */
- public static Builder builder() {
- return new ConnectionOptions.Builder()
- .setAutoConnect(false)
- .setConnectionTimeoutMillis(TimeUnit.SECONDS.toMillis(5));
- }
-
- /**
- * Builder for {@link ConnectionOptions}.
- */
- public static class Builder {
-
- private boolean mAutoConnect;
- private long mConnectionTimeoutMillis;
- private Optional mConnectionPriority = Optional.empty();
- private Optional mMtu = Optional.empty();
-
- /**
- * See {@link android.bluetooth.BluetoothDevice#connectGatt}.
- */
- public Builder setAutoConnect(boolean autoConnect) {
- this.mAutoConnect = autoConnect;
- return this;
- }
-
- /**
- * See {@link android.bluetooth.BluetoothGatt#requestConnectionPriority(int)}.
- */
- public Builder setConnectionPriority(int connectionPriority) {
- this.mConnectionPriority = Optional.of(connectionPriority);
- return this;
- }
-
- /**
- * See {@link android.bluetooth.BluetoothGatt#requestMtu(int)}.
- */
- public Builder setMtu(int mtu) {
- this.mMtu = Optional.of(mtu);
- return this;
- }
-
- /**
- * Sets the timeout for the GATT connection.
- */
- public Builder setConnectionTimeoutMillis(long connectionTimeoutMillis) {
- this.mConnectionTimeoutMillis = connectionTimeoutMillis;
- return this;
- }
-
- /**
- * Builds ConnectionOptions.
- */
- public ConnectionOptions build() {
- return new ConnectionOptions(mAutoConnect, mConnectionTimeoutMillis,
- mConnectionPriority, mMtu);
- }
- }
- }
-}
diff --git a/nearby/service/java/com/android/server/nearby/common/bluetooth/testability/NonnullProvider.java b/nearby/service/java/com/android/server/nearby/common/bluetooth/testability/NonnullProvider.java
deleted file mode 100644
index 16abd99052641ade20f1b5a7f555860047d57b5e..0000000000000000000000000000000000000000
--- a/nearby/service/java/com/android/server/nearby/common/bluetooth/testability/NonnullProvider.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.nearby.common.bluetooth.testability;
-
-/**
- * Provider that returns non-null instances.
- *
- * @param Type of provided instance.
- */
-public interface NonnullProvider {
- /** Get a non-null instance. */
- T get();
-}
diff --git a/nearby/service/java/com/android/server/nearby/common/bluetooth/testability/Testability.java b/nearby/service/java/com/android/server/nearby/common/bluetooth/testability/Testability.java
deleted file mode 100644
index 6cfdd784a490e12edcf66f12629953374f1ebf78..0000000000000000000000000000000000000000
--- a/nearby/service/java/com/android/server/nearby/common/bluetooth/testability/Testability.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.nearby.common.bluetooth.testability;
-
-import com.android.server.nearby.common.bluetooth.testability.android.bluetooth.BluetoothAdapter;
-import com.android.server.nearby.common.bluetooth.testability.android.bluetooth.BluetoothDevice;
-
-import javax.annotation.Nullable;
-
-/** Util class to convert from or to testable classes. */
-public class Testability {
- /** Wraps a Bluetooth device. */
- public static BluetoothDevice wrap(android.bluetooth.BluetoothDevice bluetoothDevice) {
- return BluetoothDevice.wrap(bluetoothDevice);
- }
-
- /** Wraps a Bluetooth adapter. */
- @Nullable
- public static BluetoothAdapter wrap(
- @Nullable android.bluetooth.BluetoothAdapter bluetoothAdapter) {
- return BluetoothAdapter.wrap(bluetoothAdapter);
- }
-}
diff --git a/nearby/service/java/com/android/server/nearby/common/bluetooth/testability/TimeProvider.java b/nearby/service/java/com/android/server/nearby/common/bluetooth/testability/TimeProvider.java
deleted file mode 100644
index a4de913d6a342ed7aaeccca9f0198f1dd4bcf621..0000000000000000000000000000000000000000
--- a/nearby/service/java/com/android/server/nearby/common/bluetooth/testability/TimeProvider.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.nearby.common.bluetooth.testability;
-
-/** Provider of time for testability. */
-public class TimeProvider {
- public long getTimeMillis() {
- return System.currentTimeMillis();
- }
-}
diff --git a/nearby/service/java/com/android/server/nearby/common/bluetooth/testability/VersionProvider.java b/nearby/service/java/com/android/server/nearby/common/bluetooth/testability/VersionProvider.java
deleted file mode 100644
index f46ea7ad05e2099552bf943830cd8fe01d201d06..0000000000000000000000000000000000000000
--- a/nearby/service/java/com/android/server/nearby/common/bluetooth/testability/VersionProvider.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.nearby.common.bluetooth.testability;
-
-import android.os.Build.VERSION;
-
-/**
- * Provider of android sdk version for testability
- */
-public class VersionProvider {
- public int getSdkInt() {
- return VERSION.SDK_INT;
- }
-}
diff --git a/nearby/service/java/com/android/server/nearby/common/bluetooth/testability/android/bluetooth/BluetoothAdapter.java b/nearby/service/java/com/android/server/nearby/common/bluetooth/testability/android/bluetooth/BluetoothAdapter.java
deleted file mode 100644
index afa2a1bc031b444aec4070ce41ba6eaa7191cacb..0000000000000000000000000000000000000000
--- a/nearby/service/java/com/android/server/nearby/common/bluetooth/testability/android/bluetooth/BluetoothAdapter.java
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.nearby.common.bluetooth.testability.android.bluetooth;
-
-import android.annotation.TargetApi;
-import android.os.Build;
-
-import com.android.server.nearby.common.bluetooth.testability.android.bluetooth.le.BluetoothLeAdvertiser;
-import com.android.server.nearby.common.bluetooth.testability.android.bluetooth.le.BluetoothLeScanner;
-
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Set;
-
-import javax.annotation.Nullable;
-
-/**
- * Mockable wrapper of {@link android.bluetooth.BluetoothAdapter}.
- */
-public class BluetoothAdapter {
- /** See {@link android.bluetooth.BluetoothAdapter#ACTION_REQUEST_ENABLE}. */
- public static final String ACTION_REQUEST_ENABLE =
- android.bluetooth.BluetoothAdapter.ACTION_REQUEST_ENABLE;
-
- /** See {@link android.bluetooth.BluetoothAdapter#ACTION_STATE_CHANGED}. */
- public static final String ACTION_STATE_CHANGED =
- android.bluetooth.BluetoothAdapter.ACTION_STATE_CHANGED;
-
- /** See {@link android.bluetooth.BluetoothAdapter#EXTRA_STATE}. */
- public static final String EXTRA_STATE =
- android.bluetooth.BluetoothAdapter.EXTRA_STATE;
-
- /** See {@link android.bluetooth.BluetoothAdapter#STATE_OFF}. */
- public static final int STATE_OFF =
- android.bluetooth.BluetoothAdapter.STATE_OFF;
-
- /** See {@link android.bluetooth.BluetoothAdapter#STATE_ON}. */
- public static final int STATE_ON =
- android.bluetooth.BluetoothAdapter.STATE_ON;
-
- /** See {@link android.bluetooth.BluetoothAdapter#STATE_TURNING_OFF}. */
- public static final int STATE_TURNING_OFF =
- android.bluetooth.BluetoothAdapter.STATE_TURNING_OFF;
-
- /** See {@link android.bluetooth.BluetoothAdapter#STATE_TURNING_ON}. */
- public static final int STATE_TURNING_ON =
- android.bluetooth.BluetoothAdapter.STATE_TURNING_ON;
-
- private final android.bluetooth.BluetoothAdapter mWrappedBluetoothAdapter;
-
- private BluetoothAdapter(android.bluetooth.BluetoothAdapter bluetoothAdapter) {
- mWrappedBluetoothAdapter = bluetoothAdapter;
- }
-
- /** See {@link android.bluetooth.BluetoothAdapter#disable()}. */
- public boolean disable() {
- return mWrappedBluetoothAdapter.disable();
- }
-
- /** See {@link android.bluetooth.BluetoothAdapter#enable()}. */
- public boolean enable() {
- return mWrappedBluetoothAdapter.enable();
- }
-
- /** See {@link android.bluetooth.BluetoothAdapter#getBluetoothLeScanner}. */
- @TargetApi(Build.VERSION_CODES.LOLLIPOP)
- @Nullable
- public BluetoothLeScanner getBluetoothLeScanner() {
- return BluetoothLeScanner.wrap(mWrappedBluetoothAdapter.getBluetoothLeScanner());
- }
-
- /** See {@link android.bluetooth.BluetoothAdapter#getBluetoothLeAdvertiser()}. */
- @TargetApi(Build.VERSION_CODES.LOLLIPOP)
- @Nullable
- public BluetoothLeAdvertiser getBluetoothLeAdvertiser() {
- return BluetoothLeAdvertiser.wrap(mWrappedBluetoothAdapter.getBluetoothLeAdvertiser());
- }
-
- /** See {@link android.bluetooth.BluetoothAdapter#getBondedDevices()}. */
- @Nullable
- public Set getBondedDevices() {
- Set bondedDevices =
- mWrappedBluetoothAdapter.getBondedDevices();
- if (bondedDevices == null) {
- return null;
- }
- Set result = new HashSet();
- for (android.bluetooth.BluetoothDevice device : bondedDevices) {
- if (device == null) {
- continue;
- }
- result.add(BluetoothDevice.wrap(device));
- }
- return Collections.unmodifiableSet(result);
- }
-
- /** See {@link android.bluetooth.BluetoothAdapter#getRemoteDevice(byte[])}. */
- public BluetoothDevice getRemoteDevice(byte[] address) {
- return BluetoothDevice.wrap(mWrappedBluetoothAdapter.getRemoteDevice(address));
- }
-
- /** See {@link android.bluetooth.BluetoothAdapter#getRemoteDevice(String)}. */
- public BluetoothDevice getRemoteDevice(String address) {
- return BluetoothDevice.wrap(mWrappedBluetoothAdapter.getRemoteDevice(address));
- }
-
- /** See {@link android.bluetooth.BluetoothAdapter#isEnabled()}. */
- public boolean isEnabled() {
- return mWrappedBluetoothAdapter.isEnabled();
- }
-
- /** See {@link android.bluetooth.BluetoothAdapter#isDiscovering()}. */
- public boolean isDiscovering() {
- return mWrappedBluetoothAdapter.isDiscovering();
- }
-
- /** See {@link android.bluetooth.BluetoothAdapter#startDiscovery()}. */
- public boolean startDiscovery() {
- return mWrappedBluetoothAdapter.startDiscovery();
- }
-
- /** See {@link android.bluetooth.BluetoothAdapter#cancelDiscovery()}. */
- public boolean cancelDiscovery() {
- return mWrappedBluetoothAdapter.cancelDiscovery();
- }
-
- /** See {@link android.bluetooth.BluetoothAdapter#getDefaultAdapter()}. */
- @Nullable
- public static BluetoothAdapter getDefaultAdapter() {
- android.bluetooth.BluetoothAdapter adapter =
- android.bluetooth.BluetoothAdapter.getDefaultAdapter();
- if (adapter == null) {
- return null;
- }
- return new BluetoothAdapter(adapter);
- }
-
- /** Wraps a Bluetooth adapter. */
- @Nullable
- public static BluetoothAdapter wrap(
- @Nullable android.bluetooth.BluetoothAdapter bluetoothAdapter) {
- if (bluetoothAdapter == null) {
- return null;
- }
- return new BluetoothAdapter(bluetoothAdapter);
- }
-
- /** Unwraps a Bluetooth adapter. */
- public android.bluetooth.BluetoothAdapter unwrap() {
- return mWrappedBluetoothAdapter;
- }
-}
diff --git a/nearby/service/java/com/android/server/nearby/common/bluetooth/testability/android/bluetooth/BluetoothDevice.java b/nearby/service/java/com/android/server/nearby/common/bluetooth/testability/android/bluetooth/BluetoothDevice.java
deleted file mode 100644
index 5b45f618fc1511c6ad321a95a5065208444ab16d..0000000000000000000000000000000000000000
--- a/nearby/service/java/com/android/server/nearby/common/bluetooth/testability/android/bluetooth/BluetoothDevice.java
+++ /dev/null
@@ -1,277 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.nearby.common.bluetooth.testability.android.bluetooth;
-
-import android.annotation.TargetApi;
-import android.bluetooth.BluetoothClass;
-import android.bluetooth.BluetoothSocket;
-import android.content.Context;
-import android.os.ParcelUuid;
-
-import java.io.IOException;
-import java.util.UUID;
-
-import javax.annotation.Nullable;
-
-/**
- * Mockable wrapper of {@link android.bluetooth.BluetoothDevice}.
- */
-@TargetApi(18)
-public class BluetoothDevice {
- /** See {@link android.bluetooth.BluetoothDevice#BOND_BONDED}. */
- public static final int BOND_BONDED = android.bluetooth.BluetoothDevice.BOND_BONDED;
-
- /** See {@link android.bluetooth.BluetoothDevice#BOND_BONDING}. */
- public static final int BOND_BONDING = android.bluetooth.BluetoothDevice.BOND_BONDING;
-
- /** See {@link android.bluetooth.BluetoothDevice#BOND_NONE}. */
- public static final int BOND_NONE = android.bluetooth.BluetoothDevice.BOND_NONE;
-
- /** See {@link android.bluetooth.BluetoothDevice#ACTION_ACL_CONNECTED}. */
- public static final String ACTION_ACL_CONNECTED =
- android.bluetooth.BluetoothDevice.ACTION_ACL_CONNECTED;
-
- /** See {@link android.bluetooth.BluetoothDevice#ACTION_ACL_DISCONNECT_REQUESTED}. */
- public static final String ACTION_ACL_DISCONNECT_REQUESTED =
- android.bluetooth.BluetoothDevice.ACTION_ACL_DISCONNECT_REQUESTED;
-
- /** See {@link android.bluetooth.BluetoothDevice#ACTION_ACL_DISCONNECTED}. */
- public static final String ACTION_ACL_DISCONNECTED =
- android.bluetooth.BluetoothDevice.ACTION_ACL_DISCONNECTED;
-
- /** See {@link android.bluetooth.BluetoothDevice#ACTION_BOND_STATE_CHANGED}. */
- public static final String ACTION_BOND_STATE_CHANGED =
- android.bluetooth.BluetoothDevice.ACTION_BOND_STATE_CHANGED;
-
- /** See {@link android.bluetooth.BluetoothDevice#ACTION_CLASS_CHANGED}. */
- public static final String ACTION_CLASS_CHANGED =
- android.bluetooth.BluetoothDevice.ACTION_CLASS_CHANGED;
-
- /** See {@link android.bluetooth.BluetoothDevice#ACTION_FOUND}. */
- public static final String ACTION_FOUND = android.bluetooth.BluetoothDevice.ACTION_FOUND;
-
- /** See {@link android.bluetooth.BluetoothDevice#ACTION_NAME_CHANGED}. */
- public static final String ACTION_NAME_CHANGED =
- android.bluetooth.BluetoothDevice.ACTION_NAME_CHANGED;
-
- /** See {@link android.bluetooth.BluetoothDevice#ACTION_PAIRING_REQUEST}. */
- // API 19 only
- public static final String ACTION_PAIRING_REQUEST =
- "android.bluetooth.device.action.PAIRING_REQUEST";
-
- /** See {@link android.bluetooth.BluetoothDevice#ACTION_UUID}. */
- public static final String ACTION_UUID = android.bluetooth.BluetoothDevice.ACTION_UUID;
-
- /** See {@link android.bluetooth.BluetoothDevice#DEVICE_TYPE_CLASSIC}. */
- public static final int DEVICE_TYPE_CLASSIC =
- android.bluetooth.BluetoothDevice.DEVICE_TYPE_CLASSIC;
-
- /** See {@link android.bluetooth.BluetoothDevice#DEVICE_TYPE_DUAL}. */
- public static final int DEVICE_TYPE_DUAL = android.bluetooth.BluetoothDevice.DEVICE_TYPE_DUAL;
-
- /** See {@link android.bluetooth.BluetoothDevice#DEVICE_TYPE_LE}. */
- public static final int DEVICE_TYPE_LE = android.bluetooth.BluetoothDevice.DEVICE_TYPE_LE;
-
- /** See {@link android.bluetooth.BluetoothDevice#DEVICE_TYPE_UNKNOWN}. */
- public static final int DEVICE_TYPE_UNKNOWN =
- android.bluetooth.BluetoothDevice.DEVICE_TYPE_UNKNOWN;
-
- /** See {@link android.bluetooth.BluetoothDevice#ERROR}. */
- public static final int ERROR = android.bluetooth.BluetoothDevice.ERROR;
-
- /** See {@link android.bluetooth.BluetoothDevice#EXTRA_BOND_STATE}. */
- public static final String EXTRA_BOND_STATE =
- android.bluetooth.BluetoothDevice.EXTRA_BOND_STATE;
-
- /** See {@link android.bluetooth.BluetoothDevice#EXTRA_CLASS}. */
- public static final String EXTRA_CLASS = android.bluetooth.BluetoothDevice.EXTRA_CLASS;
-
- /** See {@link android.bluetooth.BluetoothDevice#EXTRA_DEVICE}. */
- public static final String EXTRA_DEVICE = android.bluetooth.BluetoothDevice.EXTRA_DEVICE;
-
- /** See {@link android.bluetooth.BluetoothDevice#EXTRA_NAME}. */
- public static final String EXTRA_NAME = android.bluetooth.BluetoothDevice.EXTRA_NAME;
-
- /** See {@link android.bluetooth.BluetoothDevice#EXTRA_PAIRING_KEY}. */
- // API 19 only
- public static final String EXTRA_PAIRING_KEY = "android.bluetooth.device.extra.PAIRING_KEY";
-
- /** See {@link android.bluetooth.BluetoothDevice#EXTRA_PAIRING_VARIANT}. */
- // API 19 only
- public static final String EXTRA_PAIRING_VARIANT =
- "android.bluetooth.device.extra.PAIRING_VARIANT";
-
- /** See {@link android.bluetooth.BluetoothDevice#EXTRA_PREVIOUS_BOND_STATE}. */
- public static final String EXTRA_PREVIOUS_BOND_STATE =
- android.bluetooth.BluetoothDevice.EXTRA_PREVIOUS_BOND_STATE;
-
- /** See {@link android.bluetooth.BluetoothDevice#EXTRA_RSSI}. */
- public static final String EXTRA_RSSI = android.bluetooth.BluetoothDevice.EXTRA_RSSI;
-
- /** See {@link android.bluetooth.BluetoothDevice#EXTRA_UUID}. */
- public static final String EXTRA_UUID = android.bluetooth.BluetoothDevice.EXTRA_UUID;
-
- /** See {@link android.bluetooth.BluetoothDevice#PAIRING_VARIANT_PASSKEY_CONFIRMATION}. */
- // API 19 only
- public static final int PAIRING_VARIANT_PASSKEY_CONFIRMATION = 2;
-
- /** See {@link android.bluetooth.BluetoothDevice#PAIRING_VARIANT_PIN}. */
- // API 19 only
- public static final int PAIRING_VARIANT_PIN = 0;
-
- private final android.bluetooth.BluetoothDevice mWrappedBluetoothDevice;
-
- private BluetoothDevice(android.bluetooth.BluetoothDevice bluetoothDevice) {
- mWrappedBluetoothDevice = bluetoothDevice;
- }
-
- /**
- * See {@link android.bluetooth.BluetoothDevice#connectGatt(Context, boolean,
- * android.bluetooth.BluetoothGattCallback)}.
- */
- @Nullable(/* when bt service is not available */)
- public BluetoothGattWrapper connectGatt(Context context, boolean autoConnect,
- BluetoothGattCallback callback) {
- android.bluetooth.BluetoothGatt gatt =
- mWrappedBluetoothDevice.connectGatt(context, autoConnect, callback.unwrap());
- if (gatt == null) {
- return null;
- }
- return BluetoothGattWrapper.wrap(gatt);
- }
-
- /**
- * See {@link android.bluetooth.BluetoothDevice#connectGatt(Context, boolean,
- * android.bluetooth.BluetoothGattCallback, int)}.
- */
- @TargetApi(23)
- @Nullable(/* when bt service is not available */)
- public BluetoothGattWrapper connectGatt(Context context, boolean autoConnect,
- BluetoothGattCallback callback, int transport) {
- android.bluetooth.BluetoothGatt gatt =
- mWrappedBluetoothDevice.connectGatt(
- context, autoConnect, callback.unwrap(), transport);
- if (gatt == null) {
- return null;
- }
- return BluetoothGattWrapper.wrap(gatt);
- }
-
-
- /**
- * See {@link android.bluetooth.BluetoothDevice#createRfcommSocketToServiceRecord(UUID)}.
- */
- public BluetoothSocket createRfcommSocketToServiceRecord(UUID uuid) throws IOException {
- return mWrappedBluetoothDevice.createRfcommSocketToServiceRecord(uuid);
- }
-
- /**
- * See
- * {@link android.bluetooth.BluetoothDevice#createInsecureRfcommSocketToServiceRecord(UUID)}.
- */
- public BluetoothSocket createInsecureRfcommSocketToServiceRecord(UUID uuid) throws IOException {
- return mWrappedBluetoothDevice.createInsecureRfcommSocketToServiceRecord(uuid);
- }
-
- /** See {@link android.bluetooth.BluetoothDevice#setPin(byte[])}. */
- @TargetApi(19)
- public boolean setPairingConfirmation(byte[] pin) {
- return mWrappedBluetoothDevice.setPin(pin);
- }
-
- /** See {@link android.bluetooth.BluetoothDevice#setPairingConfirmation(boolean)}. */
- public boolean setPairingConfirmation(boolean confirm) {
- return mWrappedBluetoothDevice.setPairingConfirmation(confirm);
- }
-
- /** See {@link android.bluetooth.BluetoothDevice#fetchUuidsWithSdp()}. */
- public boolean fetchUuidsWithSdp() {
- return mWrappedBluetoothDevice.fetchUuidsWithSdp();
- }
-
- /** See {@link android.bluetooth.BluetoothDevice#createBond()}. */
- public boolean createBond() {
- return mWrappedBluetoothDevice.createBond();
- }
-
- /** See {@link android.bluetooth.BluetoothDevice#getUuids()}. */
- @Nullable(/* on error */)
- public ParcelUuid[] getUuids() {
- return mWrappedBluetoothDevice.getUuids();
- }
-
- /** See {@link android.bluetooth.BluetoothDevice#getBondState()}. */
- public int getBondState() {
- return mWrappedBluetoothDevice.getBondState();
- }
-
- /** See {@link android.bluetooth.BluetoothDevice#getAddress()}. */
- public String getAddress() {
- return mWrappedBluetoothDevice.getAddress();
- }
-
- /** See {@link android.bluetooth.BluetoothDevice#getBluetoothClass()}. */
- @Nullable(/* on error */)
- public BluetoothClass getBluetoothClass() {
- return mWrappedBluetoothDevice.getBluetoothClass();
- }
-
- /** See {@link android.bluetooth.BluetoothDevice#getType()}. */
- public int getType() {
- return mWrappedBluetoothDevice.getType();
- }
-
- /** See {@link android.bluetooth.BluetoothDevice#getName()}. */
- @Nullable(/* on error */)
- public String getName() {
- return mWrappedBluetoothDevice.getName();
- }
-
- /** See {@link android.bluetooth.BluetoothDevice#toString()}. */
- @Override
- public String toString() {
- return mWrappedBluetoothDevice.toString();
- }
-
- /** See {@link android.bluetooth.BluetoothDevice#hashCode()}. */
- @Override
- public int hashCode() {
- return mWrappedBluetoothDevice.hashCode();
- }
-
- /** See {@link android.bluetooth.BluetoothDevice#equals(Object)}. */
- @Override
- public boolean equals(@Nullable Object o) {
- if (o == this) {
- return true;
- }
- if (!(o instanceof BluetoothDevice)) {
- return false;
- }
- return mWrappedBluetoothDevice.equals(((BluetoothDevice) o).unwrap());
- }
-
- /** Unwraps a Bluetooth device. */
- public android.bluetooth.BluetoothDevice unwrap() {
- return mWrappedBluetoothDevice;
- }
-
- /** Wraps a Bluetooth device. */
- public static BluetoothDevice wrap(android.bluetooth.BluetoothDevice bluetoothDevice) {
- return new BluetoothDevice(bluetoothDevice);
- }
-}
diff --git a/nearby/service/java/com/android/server/nearby/common/bluetooth/testability/android/bluetooth/BluetoothGattCallback.java b/nearby/service/java/com/android/server/nearby/common/bluetooth/testability/android/bluetooth/BluetoothGattCallback.java
deleted file mode 100644
index d36cfa251758b2b06d38db01ff3aa95717eebe87..0000000000000000000000000000000000000000
--- a/nearby/service/java/com/android/server/nearby/common/bluetooth/testability/android/bluetooth/BluetoothGattCallback.java
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.nearby.common.bluetooth.testability.android.bluetooth;
-
-import android.bluetooth.BluetoothGattCharacteristic;
-import android.bluetooth.BluetoothGattDescriptor;
-
-/**
- * Wrapper of {@link android.bluetooth.BluetoothGattCallback} that uses mockable objects.
- */
-public abstract class BluetoothGattCallback {
-
- private final android.bluetooth.BluetoothGattCallback mWrappedBluetoothGattCallback =
- new InternalBluetoothGattCallback();
-
- /**
- * See {@link android.bluetooth.BluetoothGattCallback#onConnectionStateChange(
- * android.bluetooth.BluetoothGatt, int, int)}
- */
- public void onConnectionStateChange(BluetoothGattWrapper gatt, int status, int newState) {}
-
- /**
- * See {@link android.bluetooth.BluetoothGattCallback#onServicesDiscovered(
- * android.bluetooth.BluetoothGatt,int)}
- */
- public void onServicesDiscovered(BluetoothGattWrapper gatt, int status) {}
-
- /**
- * See {@link android.bluetooth.BluetoothGattCallback#onCharacteristicRead(
- * android.bluetooth.BluetoothGatt, BluetoothGattCharacteristic, int)}
- */
- public void onCharacteristicRead(BluetoothGattWrapper gatt, BluetoothGattCharacteristic
- characteristic, int status) {}
-
- /**
- * See {@link android.bluetooth.BluetoothGattCallback#onCharacteristicWrite(
- * android.bluetooth.BluetoothGatt, BluetoothGattCharacteristic, int)}
- */
- public void onCharacteristicWrite(BluetoothGattWrapper gatt,
- BluetoothGattCharacteristic characteristic, int status) {}
-
- /**
- * See {@link android.bluetooth.BluetoothGattCallback#onDescriptorRead(
- * android.bluetooth.BluetoothGatt, BluetoothGattDescriptor, int)}
- */
- public void onDescriptorRead(
- BluetoothGattWrapper gatt, BluetoothGattDescriptor descriptor, int status) {}
-
- /**
- * See {@link android.bluetooth.BluetoothGattCallback#onDescriptorWrite(
- * android.bluetooth.BluetoothGatt, BluetoothGattDescriptor, int)}
- */
- public void onDescriptorWrite(BluetoothGattWrapper gatt, BluetoothGattDescriptor descriptor,
- int status) {}
-
- /**
- * See {@link android.bluetooth.BluetoothGattCallback#onReadRemoteRssi(
- * android.bluetooth.BluetoothGatt, int, int)}
- */
- public void onReadRemoteRssi(BluetoothGattWrapper gatt, int rssi, int status) {}
-
- /**
- * See {@link android.bluetooth.BluetoothGattCallback#onReliableWriteCompleted(
- * android.bluetooth.BluetoothGatt, int)}
- */
- public void onReliableWriteCompleted(BluetoothGattWrapper gatt, int status) {}
-
- /**
- * See
- * {@link android.bluetooth.BluetoothGattCallback#onMtuChanged(android.bluetooth.BluetoothGatt,
- * int, int)}
- */
- public void onMtuChanged(BluetoothGattWrapper gatt, int mtu, int status) {}
-
- /**
- * See
- * {@link android.bluetooth.BluetoothGattCallback#onCharacteristicChanged(
- * android.bluetooth.BluetoothGatt, BluetoothGattCharacteristic)}
- */
- public void onCharacteristicChanged(BluetoothGattWrapper gatt,
- BluetoothGattCharacteristic characteristic) {}
-
- /** Unwraps a Bluetooth Gatt callback. */
- public android.bluetooth.BluetoothGattCallback unwrap() {
- return mWrappedBluetoothGattCallback;
- }
-
- /** Forward callback to testable instance. */
- private class InternalBluetoothGattCallback extends android.bluetooth.BluetoothGattCallback {
- @Override
- public void onConnectionStateChange(android.bluetooth.BluetoothGatt gatt, int status,
- int newState) {
- BluetoothGattCallback.this.onConnectionStateChange(BluetoothGattWrapper.wrap(gatt),
- status, newState);
- }
-
- @Override
- public void onServicesDiscovered(android.bluetooth.BluetoothGatt gatt, int status) {
- BluetoothGattCallback.this.onServicesDiscovered(BluetoothGattWrapper.wrap(gatt),
- status);
- }
-
- @Override
- public void onCharacteristicRead(android.bluetooth.BluetoothGatt gatt,
- BluetoothGattCharacteristic characteristic, int status) {
- BluetoothGattCallback.this.onCharacteristicRead(
- BluetoothGattWrapper.wrap(gatt), characteristic, status);
- }
-
- @Override
- public void onCharacteristicWrite(android.bluetooth.BluetoothGatt gatt,
- BluetoothGattCharacteristic characteristic, int status) {
- BluetoothGattCallback.this.onCharacteristicWrite(
- BluetoothGattWrapper.wrap(gatt), characteristic, status);
- }
-
- @Override
- public void onDescriptorRead(android.bluetooth.BluetoothGatt gatt,
- BluetoothGattDescriptor descriptor, int status) {
- BluetoothGattCallback.this.onDescriptorRead(
- BluetoothGattWrapper.wrap(gatt), descriptor, status);
- }
-
- @Override
- public void onDescriptorWrite(android.bluetooth.BluetoothGatt gatt,
- BluetoothGattDescriptor descriptor, int status) {
- BluetoothGattCallback.this.onDescriptorWrite(
- BluetoothGattWrapper.wrap(gatt), descriptor, status);
- }
-
- @Override
- public void onReadRemoteRssi(android.bluetooth.BluetoothGatt gatt, int rssi, int status) {
- BluetoothGattCallback.this.onReadRemoteRssi(BluetoothGattWrapper.wrap(gatt), rssi,
- status);
- }
-
- @Override
- public void onReliableWriteCompleted(android.bluetooth.BluetoothGatt gatt, int status) {
- BluetoothGattCallback.this.onReliableWriteCompleted(BluetoothGattWrapper.wrap(gatt),
- status);
- }
-
- @Override
- public void onMtuChanged(android.bluetooth.BluetoothGatt gatt, int mtu, int status) {
- BluetoothGattCallback.this.onMtuChanged(BluetoothGattWrapper.wrap(gatt), mtu, status);
- }
-
- @Override
- public void onCharacteristicChanged(android.bluetooth.BluetoothGatt gatt,
- BluetoothGattCharacteristic characteristic) {
- BluetoothGattCallback.this.onCharacteristicChanged(
- BluetoothGattWrapper.wrap(gatt), characteristic);
- }
- }
-}
diff --git a/nearby/service/java/com/android/server/nearby/common/bluetooth/testability/android/bluetooth/BluetoothGattServer.java b/nearby/service/java/com/android/server/nearby/common/bluetooth/testability/android/bluetooth/BluetoothGattServer.java
deleted file mode 100644
index 3f6f3617febf0eb80f1da077348cc6486a438133..0000000000000000000000000000000000000000
--- a/nearby/service/java/com/android/server/nearby/common/bluetooth/testability/android/bluetooth/BluetoothGattServer.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.nearby.common.bluetooth.testability.android.bluetooth;
-
-import android.bluetooth.BluetoothGattCharacteristic;
-import android.bluetooth.BluetoothGattService;
-
-import java.util.UUID;
-
-import javax.annotation.Nullable;
-
-/**
- * Mockable wrapper of {@link android.bluetooth.BluetoothGattServer}.
- */
-public class BluetoothGattServer {
-
- /** See {@link android.bluetooth.BluetoothGattServer#STATE_CONNECTED}. */
- public static final int STATE_CONNECTED = android.bluetooth.BluetoothGattServer.STATE_CONNECTED;
-
- /** See {@link android.bluetooth.BluetoothGattServer#STATE_DISCONNECTED}. */
- public static final int STATE_DISCONNECTED =
- android.bluetooth.BluetoothGattServer.STATE_DISCONNECTED;
-
- private android.bluetooth.BluetoothGattServer mWrappedInstance;
-
- private BluetoothGattServer(android.bluetooth.BluetoothGattServer instance) {
- mWrappedInstance = instance;
- }
-
- /** Wraps a Bluetooth Gatt server. */
- @Nullable
- public static BluetoothGattServer wrap(
- @Nullable android.bluetooth.BluetoothGattServer instance) {
- if (instance == null) {
- return null;
- }
- return new BluetoothGattServer(instance);
- }
-
- /**
- * See {@link android.bluetooth.BluetoothGattServer#connect(
- * android.bluetooth.BluetoothDevice, boolean)}
- */
- public boolean connect(BluetoothDevice device, boolean autoConnect) {
- return mWrappedInstance.connect(device.unwrap(), autoConnect);
- }
-
- /** See {@link android.bluetooth.BluetoothGattServer#addService(BluetoothGattService)}. */
- public boolean addService(BluetoothGattService service) {
- return mWrappedInstance.addService(service);
- }
-
- /** See {@link android.bluetooth.BluetoothGattServer#clearServices()}. */
- public void clearServices() {
- mWrappedInstance.clearServices();
- }
-
- /** See {@link android.bluetooth.BluetoothGattServer#close()}. */
- public void close() {
- mWrappedInstance.close();
- }
-
- /**
- * See {@link android.bluetooth.BluetoothGattServer#notifyCharacteristicChanged(
- * android.bluetooth.BluetoothDevice, BluetoothGattCharacteristic, boolean)}.
- */
- public boolean notifyCharacteristicChanged(BluetoothDevice device,
- BluetoothGattCharacteristic characteristic, boolean confirm) {
- return mWrappedInstance.notifyCharacteristicChanged(
- device.unwrap(), characteristic, confirm);
- }
-
- /**
- * See {@link android.bluetooth.BluetoothGattServer#sendResponse(
- * android.bluetooth.BluetoothDevice, int, int, int, byte[])}.
- */
- public void sendResponse(BluetoothDevice device, int requestId, int status, int offset,
- @Nullable byte[] value) {
- mWrappedInstance.sendResponse(device.unwrap(), requestId, status, offset, value);
- }
-
- /**
- * See {@link android.bluetooth.BluetoothGattServer#cancelConnection(
- * android.bluetooth.BluetoothDevice)}.
- */
- public void cancelConnection(BluetoothDevice device) {
- mWrappedInstance.cancelConnection(device.unwrap());
- }
-
- /** See {@link android.bluetooth.BluetoothGattServer#getService(UUID uuid)}. */
- public BluetoothGattService getService(UUID uuid) {
- return mWrappedInstance.getService(uuid);
- }
-}
diff --git a/nearby/service/java/com/android/server/nearby/common/bluetooth/testability/android/bluetooth/BluetoothGattServerCallback.java b/nearby/service/java/com/android/server/nearby/common/bluetooth/testability/android/bluetooth/BluetoothGattServerCallback.java
deleted file mode 100644
index 875dad562f5986857eae7fd845467654bce73e2a..0000000000000000000000000000000000000000
--- a/nearby/service/java/com/android/server/nearby/common/bluetooth/testability/android/bluetooth/BluetoothGattServerCallback.java
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.nearby.common.bluetooth.testability.android.bluetooth;
-
-import android.bluetooth.BluetoothGattCharacteristic;
-import android.bluetooth.BluetoothGattDescriptor;
-import android.bluetooth.BluetoothGattService;
-
-/**
- * Wrapper of {@link android.bluetooth.BluetoothGattServerCallback} that uses mockable objects.
- */
-public abstract class BluetoothGattServerCallback {
-
- private final android.bluetooth.BluetoothGattServerCallback mWrappedInstance =
- new InternalBluetoothGattServerCallback();
-
- /**
- * See {@link android.bluetooth.BluetoothGattServerCallback#onCharacteristicReadRequest(
- * android.bluetooth.BluetoothDevice, int, int, BluetoothGattCharacteristic)}
- */
- public void onCharacteristicReadRequest(BluetoothDevice device, int requestId,
- int offset, BluetoothGattCharacteristic characteristic) {}
-
- /**
- * See {@link android.bluetooth.BluetoothGattServerCallback#onCharacteristicWriteRequest(
- * android.bluetooth.BluetoothDevice, int, BluetoothGattCharacteristic, boolean, boolean, int,
- * byte[])}
- */
- public void onCharacteristicWriteRequest(BluetoothDevice device,
- int requestId,
- BluetoothGattCharacteristic characteristic,
- boolean preparedWrite,
- boolean responseNeeded,
- int offset,
- byte[] value) {}
-
- /**
- * See {@link android.bluetooth.BluetoothGattServerCallback#onConnectionStateChange(
- * android.bluetooth.BluetoothDevice, int, int)}
- */
- public void onConnectionStateChange(BluetoothDevice device, int status, int newState) {}
-
- /**
- * See {@link android.bluetooth.BluetoothGattServerCallback#onDescriptorReadRequest(
- * android.bluetooth.BluetoothDevice, int, int, BluetoothGattDescriptor)}
- */
- public void onDescriptorReadRequest(BluetoothDevice device, int requestId, int offset,
- BluetoothGattDescriptor descriptor) {}
-
- /**
- * See {@link android.bluetooth.BluetoothGattServerCallback#onDescriptorWriteRequest(
- * android.bluetooth.BluetoothDevice, int, BluetoothGattDescriptor, boolean, boolean, int,
- * byte[])}
- */
- public void onDescriptorWriteRequest(BluetoothDevice device,
- int requestId,
- BluetoothGattDescriptor descriptor,
- boolean preparedWrite,
- boolean responseNeeded,
- int offset,
- byte[] value) {}
-
- /**
- * See {@link android.bluetooth.BluetoothGattServerCallback#onExecuteWrite(
- * android.bluetooth.BluetoothDevice, int, boolean)}
- */
- public void onExecuteWrite(BluetoothDevice device, int requestId, boolean execute) {}
-
- /**
- * See {@link android.bluetooth.BluetoothGattServerCallback#onMtuChanged(
- * android.bluetooth.BluetoothDevice, int)}
- */
- public void onMtuChanged(BluetoothDevice device, int mtu) {}
-
- /**
- * See {@link android.bluetooth.BluetoothGattServerCallback#onNotificationSent(
- * android.bluetooth.BluetoothDevice, int)}
- */
- public void onNotificationSent(BluetoothDevice device, int status) {}
-
- /**
- * See {@link android.bluetooth.BluetoothGattServerCallback#onServiceAdded(int,
- * BluetoothGattService)}
- */
- public void onServiceAdded(int status, BluetoothGattService service) {}
-
- /** Unwraps a Bluetooth Gatt server callback. */
- public android.bluetooth.BluetoothGattServerCallback unwrap() {
- return mWrappedInstance;
- }
-
- /** Forward callback to testable instance. */
- private class InternalBluetoothGattServerCallback extends
- android.bluetooth.BluetoothGattServerCallback {
- @Override
- public void onCharacteristicReadRequest(android.bluetooth.BluetoothDevice device,
- int requestId, int offset, BluetoothGattCharacteristic characteristic) {
- BluetoothGattServerCallback.this.onCharacteristicReadRequest(
- BluetoothDevice.wrap(device), requestId, offset, characteristic);
- }
-
- @Override
- public void onCharacteristicWriteRequest(android.bluetooth.BluetoothDevice device,
- int requestId,
- BluetoothGattCharacteristic characteristic,
- boolean preparedWrite,
- boolean responseNeeded,
- int offset,
- byte[] value) {
- BluetoothGattServerCallback.this.onCharacteristicWriteRequest(
- BluetoothDevice.wrap(device),
- requestId,
- characteristic,
- preparedWrite,
- responseNeeded,
- offset,
- value);
- }
-
- @Override
- public void onConnectionStateChange(android.bluetooth.BluetoothDevice device, int status,
- int newState) {
- BluetoothGattServerCallback.this.onConnectionStateChange(
- BluetoothDevice.wrap(device), status, newState);
- }
-
- @Override
- public void onDescriptorReadRequest(android.bluetooth.BluetoothDevice device, int requestId,
- int offset, BluetoothGattDescriptor descriptor) {
- BluetoothGattServerCallback.this.onDescriptorReadRequest(BluetoothDevice.wrap(device),
- requestId, offset, descriptor);
- }
-
- @Override
- public void onDescriptorWriteRequest(android.bluetooth.BluetoothDevice device,
- int requestId,
- BluetoothGattDescriptor descriptor,
- boolean preparedWrite,
- boolean responseNeeded,
- int offset,
- byte[] value) {
- BluetoothGattServerCallback.this.onDescriptorWriteRequest(BluetoothDevice.wrap(device),
- requestId,
- descriptor,
- preparedWrite,
- responseNeeded,
- offset,
- value);
- }
-
- @Override
- public void onExecuteWrite(android.bluetooth.BluetoothDevice device, int requestId,
- boolean execute) {
- BluetoothGattServerCallback.this.onExecuteWrite(BluetoothDevice.wrap(device), requestId,
- execute);
- }
-
- @Override
- public void onMtuChanged(android.bluetooth.BluetoothDevice device, int mtu) {
- BluetoothGattServerCallback.this.onMtuChanged(BluetoothDevice.wrap(device), mtu);
- }
-
- @Override
- public void onNotificationSent(android.bluetooth.BluetoothDevice device, int status) {
- BluetoothGattServerCallback.this.onNotificationSent(
- BluetoothDevice.wrap(device), status);
- }
-
- @Override
- public void onServiceAdded(int status, BluetoothGattService service) {
- BluetoothGattServerCallback.this.onServiceAdded(status, service);
- }
- }
-}
diff --git a/nearby/service/java/com/android/server/nearby/common/bluetooth/testability/android/bluetooth/BluetoothGattWrapper.java b/nearby/service/java/com/android/server/nearby/common/bluetooth/testability/android/bluetooth/BluetoothGattWrapper.java
deleted file mode 100644
index 453ee5d694bdb8629bd501d61c5b1b3704caee24..0000000000000000000000000000000000000000
--- a/nearby/service/java/com/android/server/nearby/common/bluetooth/testability/android/bluetooth/BluetoothGattWrapper.java
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.nearby.common.bluetooth.testability.android.bluetooth;
-
-import android.annotation.TargetApi;
-import android.bluetooth.BluetoothGattCharacteristic;
-import android.bluetooth.BluetoothGattDescriptor;
-import android.bluetooth.BluetoothGattService;
-import android.os.Build;
-
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.util.List;
-import java.util.UUID;
-
-import javax.annotation.Nullable;
-
-/** Mockable wrapper of {@link android.bluetooth.BluetoothGatt}. */
-@TargetApi(Build.VERSION_CODES.TIRAMISU)
-public class BluetoothGattWrapper {
- private final android.bluetooth.BluetoothGatt mWrappedBluetoothGatt;
-
- private BluetoothGattWrapper(android.bluetooth.BluetoothGatt bluetoothGatt) {
- mWrappedBluetoothGatt = bluetoothGatt;
- }
-
- /** See {@link android.bluetooth.BluetoothGatt#getDevice()}. */
- public BluetoothDevice getDevice() {
- return BluetoothDevice.wrap(mWrappedBluetoothGatt.getDevice());
- }
-
- /** See {@link android.bluetooth.BluetoothGatt#getServices()}. */
- public List getServices() {
- return mWrappedBluetoothGatt.getServices();
- }
-
- /** See {@link android.bluetooth.BluetoothGatt#getService(UUID)}. */
- @Nullable(/* null if service is not found */)
- public BluetoothGattService getService(UUID uuid) {
- return mWrappedBluetoothGatt.getService(uuid);
- }
-
- /** See {@link android.bluetooth.BluetoothGatt#discoverServices()}. */
- public boolean discoverServices() {
- return mWrappedBluetoothGatt.discoverServices();
- }
-
- /**
- * Hidden method. Clears the internal cache and forces a refresh of the services from the remote
- * device.
- */
- // TODO(b/201300471): remove refresh call using reflection.
- public boolean refresh() {
- try {
- Method refreshMethod = android.bluetooth.BluetoothGatt.class.getMethod("refresh");
- return (Boolean) refreshMethod.invoke(mWrappedBluetoothGatt);
- } catch (NoSuchMethodException
- | IllegalAccessException
- | IllegalArgumentException
- | InvocationTargetException e) {
- return false;
- }
- }
-
- /**
- * See {@link android.bluetooth.BluetoothGatt#readCharacteristic(BluetoothGattCharacteristic)}.
- */
- public boolean readCharacteristic(BluetoothGattCharacteristic characteristic) {
- return mWrappedBluetoothGatt.readCharacteristic(characteristic);
- }
-
- /**
- * See {@link android.bluetooth.BluetoothGatt#writeCharacteristic(BluetoothGattCharacteristic,
- * byte[], int)} .
- */
- public int writeCharacteristic(BluetoothGattCharacteristic characteristic, byte[] value,
- int writeType) {
- return mWrappedBluetoothGatt.writeCharacteristic(characteristic, value, writeType);
- }
-
- /** See {@link android.bluetooth.BluetoothGatt#readDescriptor(BluetoothGattDescriptor)}. */
- public boolean readDescriptor(BluetoothGattDescriptor descriptor) {
- return mWrappedBluetoothGatt.readDescriptor(descriptor);
- }
-
- /**
- * See {@link android.bluetooth.BluetoothGatt#writeDescriptor(BluetoothGattDescriptor,
- * byte[])}.
- */
- public int writeDescriptor(BluetoothGattDescriptor descriptor, byte[] value) {
- return mWrappedBluetoothGatt.writeDescriptor(descriptor, value);
- }
-
- /** See {@link android.bluetooth.BluetoothGatt#readRemoteRssi()}. */
- public boolean readRemoteRssi() {
- return mWrappedBluetoothGatt.readRemoteRssi();
- }
-
- /** See {@link android.bluetooth.BluetoothGatt#requestConnectionPriority(int)}. */
- public boolean requestConnectionPriority(int connectionPriority) {
- return mWrappedBluetoothGatt.requestConnectionPriority(connectionPriority);
- }
-
- /** See {@link android.bluetooth.BluetoothGatt#requestMtu(int)}. */
- public boolean requestMtu(int mtu) {
- return mWrappedBluetoothGatt.requestMtu(mtu);
- }
-
- /** See {@link android.bluetooth.BluetoothGatt#setCharacteristicNotification}. */
- public boolean setCharacteristicNotification(
- BluetoothGattCharacteristic characteristic, boolean enable) {
- return mWrappedBluetoothGatt.setCharacteristicNotification(characteristic, enable);
- }
-
- /** See {@link android.bluetooth.BluetoothGatt#disconnect()}. */
- public void disconnect() {
- mWrappedBluetoothGatt.disconnect();
- }
-
- /** See {@link android.bluetooth.BluetoothGatt#close()}. */
- public void close() {
- mWrappedBluetoothGatt.close();
- }
-
- /** See {@link android.bluetooth.BluetoothGatt#hashCode()}. */
- @Override
- public int hashCode() {
- return mWrappedBluetoothGatt.hashCode();
- }
-
- /** See {@link android.bluetooth.BluetoothGatt#equals(Object)}. */
- @Override
- public boolean equals(@Nullable Object o) {
- if (o == this) {
- return true;
- }
- if (!(o instanceof BluetoothGattWrapper)) {
- return false;
- }
- return mWrappedBluetoothGatt.equals(((BluetoothGattWrapper) o).unwrap());
- }
-
- /** Unwraps a Bluetooth Gatt instance. */
- public android.bluetooth.BluetoothGatt unwrap() {
- return mWrappedBluetoothGatt;
- }
-
- /** Wraps a Bluetooth Gatt instance. */
- public static BluetoothGattWrapper wrap(android.bluetooth.BluetoothGatt gatt) {
- return new BluetoothGattWrapper(gatt);
- }
-}
diff --git a/nearby/service/java/com/android/server/nearby/common/bluetooth/testability/android/bluetooth/le/BluetoothLeAdvertiser.java b/nearby/service/java/com/android/server/nearby/common/bluetooth/testability/android/bluetooth/le/BluetoothLeAdvertiser.java
deleted file mode 100644
index 6fe44324a6c4afaa618a3f29b618595d0afb9ec0..0000000000000000000000000000000000000000
--- a/nearby/service/java/com/android/server/nearby/common/bluetooth/testability/android/bluetooth/le/BluetoothLeAdvertiser.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.nearby.common.bluetooth.testability.android.bluetooth.le;
-
-import android.annotation.TargetApi;
-import android.bluetooth.le.AdvertiseCallback;
-import android.bluetooth.le.AdvertiseData;
-import android.bluetooth.le.AdvertiseSettings;
-import android.os.Build;
-
-import javax.annotation.Nullable;
-
-/**
- * Mockable wrapper of {@link android.bluetooth.le.BluetoothLeAdvertiser}.
- */
-@TargetApi(Build.VERSION_CODES.LOLLIPOP)
-public class BluetoothLeAdvertiser {
-
- private final android.bluetooth.le.BluetoothLeAdvertiser mWrappedInstance;
-
- private BluetoothLeAdvertiser(
- android.bluetooth.le.BluetoothLeAdvertiser bluetoothLeAdvertiser) {
- mWrappedInstance = bluetoothLeAdvertiser;
- }
-
- /**
- * See {@link android.bluetooth.le.BluetoothLeAdvertiser#startAdvertising(AdvertiseSettings,
- * AdvertiseData, AdvertiseCallback)}.
- */
- public void startAdvertising(AdvertiseSettings settings, AdvertiseData advertiseData,
- AdvertiseCallback callback) {
- mWrappedInstance.startAdvertising(settings, advertiseData, callback);
- }
-
- /**
- * See {@link android.bluetooth.le.BluetoothLeAdvertiser#startAdvertising(AdvertiseSettings,
- * AdvertiseData, AdvertiseData, AdvertiseCallback)}.
- */
- public void startAdvertising(AdvertiseSettings settings, AdvertiseData advertiseData,
- AdvertiseData scanResponse, AdvertiseCallback callback) {
- mWrappedInstance.startAdvertising(settings, advertiseData, scanResponse, callback);
- }
-
- /**
- * See {@link android.bluetooth.le.BluetoothLeAdvertiser#stopAdvertising(AdvertiseCallback)}.
- */
- public void stopAdvertising(AdvertiseCallback callback) {
- mWrappedInstance.stopAdvertising(callback);
- }
-
- /** Wraps a Bluetooth LE advertiser. */
- @Nullable
- public static BluetoothLeAdvertiser wrap(
- @Nullable android.bluetooth.le.BluetoothLeAdvertiser bluetoothLeAdvertiser) {
- if (bluetoothLeAdvertiser == null) {
- return null;
- }
- return new BluetoothLeAdvertiser(bluetoothLeAdvertiser);
- }
-}
diff --git a/nearby/service/java/com/android/server/nearby/common/bluetooth/testability/android/bluetooth/le/BluetoothLeScanner.java b/nearby/service/java/com/android/server/nearby/common/bluetooth/testability/android/bluetooth/le/BluetoothLeScanner.java
deleted file mode 100644
index 8a13abe5d3e87ee47178da34e17b72d66072f10a..0000000000000000000000000000000000000000
--- a/nearby/service/java/com/android/server/nearby/common/bluetooth/testability/android/bluetooth/le/BluetoothLeScanner.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.nearby.common.bluetooth.testability.android.bluetooth.le;
-
-import android.annotation.TargetApi;
-import android.app.PendingIntent;
-import android.bluetooth.le.ScanFilter;
-import android.bluetooth.le.ScanSettings;
-import android.os.Build;
-
-import java.util.List;
-
-import javax.annotation.Nullable;
-
-/**
- * Mockable wrapper of {@link android.bluetooth.le.BluetoothLeScanner}.
- */
-@TargetApi(Build.VERSION_CODES.LOLLIPOP)
-public class BluetoothLeScanner {
-
- private final android.bluetooth.le.BluetoothLeScanner mWrappedBluetoothLeScanner;
-
- private BluetoothLeScanner(android.bluetooth.le.BluetoothLeScanner bluetoothLeScanner) {
- mWrappedBluetoothLeScanner = bluetoothLeScanner;
- }
-
- /**
- * See {@link android.bluetooth.le.BluetoothLeScanner#startScan(List, ScanSettings,
- * android.bluetooth.le.ScanCallback)}.
- */
- public void startScan(List filters, ScanSettings settings,
- ScanCallback callback) {
- mWrappedBluetoothLeScanner.startScan(filters, settings, callback.unwrap());
- }
-
- /**
- * See {@link android.bluetooth.le.BluetoothLeScanner#startScan(List, ScanSettings,
- * PendingIntent)}.
- */
- public void startScan(
- List filters, ScanSettings settings, PendingIntent callbackIntent) {
- mWrappedBluetoothLeScanner.startScan(filters, settings, callbackIntent);
- }
-
- /**
- * See {@link
- * android.bluetooth.le.BluetoothLeScanner#startScan(android.bluetooth.le.ScanCallback)}.
- */
- public void startScan(ScanCallback callback) {
- mWrappedBluetoothLeScanner.startScan(callback.unwrap());
- }
-
- /**
- * See
- * {@link android.bluetooth.le.BluetoothLeScanner#stopScan(android.bluetooth.le.ScanCallback)}.
- */
- public void stopScan(ScanCallback callback) {
- mWrappedBluetoothLeScanner.stopScan(callback.unwrap());
- }
-
- /** See {@link android.bluetooth.le.BluetoothLeScanner#stopScan(PendingIntent)}. */
- public void stopScan(PendingIntent callbackIntent) {
- mWrappedBluetoothLeScanner.stopScan(callbackIntent);
- }
-
- /** Wraps a Bluetooth LE scanner. */
- @Nullable
- public static BluetoothLeScanner wrap(
- @Nullable android.bluetooth.le.BluetoothLeScanner bluetoothLeScanner) {
- if (bluetoothLeScanner == null) {
- return null;
- }
- return new BluetoothLeScanner(bluetoothLeScanner);
- }
-}
diff --git a/nearby/service/java/com/android/server/nearby/common/bluetooth/testability/android/bluetooth/le/ScanCallback.java b/nearby/service/java/com/android/server/nearby/common/bluetooth/testability/android/bluetooth/le/ScanCallback.java
deleted file mode 100644
index 70926a77191481a665b34b89dc28a8103bffcbdf..0000000000000000000000000000000000000000
--- a/nearby/service/java/com/android/server/nearby/common/bluetooth/testability/android/bluetooth/le/ScanCallback.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.nearby.common.bluetooth.testability.android.bluetooth.le;
-
-import android.annotation.TargetApi;
-import android.os.Build;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Wrapper of {@link android.bluetooth.le.ScanCallback} that uses mockable objects.
- */
-@TargetApi(Build.VERSION_CODES.LOLLIPOP)
-public abstract class ScanCallback {
-
- /** See {@link android.bluetooth.le.ScanCallback#SCAN_FAILED_ALREADY_STARTED} */
- public static final int SCAN_FAILED_ALREADY_STARTED =
- android.bluetooth.le.ScanCallback.SCAN_FAILED_ALREADY_STARTED;
-
- /** See {@link android.bluetooth.le.ScanCallback#SCAN_FAILED_APPLICATION_REGISTRATION_FAILED} */
- public static final int SCAN_FAILED_APPLICATION_REGISTRATION_FAILED =
- android.bluetooth.le.ScanCallback.SCAN_FAILED_APPLICATION_REGISTRATION_FAILED;
-
- /** See {@link android.bluetooth.le.ScanCallback#SCAN_FAILED_FEATURE_UNSUPPORTED} */
- public static final int SCAN_FAILED_FEATURE_UNSUPPORTED =
- android.bluetooth.le.ScanCallback.SCAN_FAILED_FEATURE_UNSUPPORTED;
-
- /** See {@link android.bluetooth.le.ScanCallback#SCAN_FAILED_INTERNAL_ERROR} */
- public static final int SCAN_FAILED_INTERNAL_ERROR =
- android.bluetooth.le.ScanCallback.SCAN_FAILED_INTERNAL_ERROR;
-
- private final android.bluetooth.le.ScanCallback mWrappedScanCallback =
- new InternalScanCallback();
-
- /**
- * See {@link android.bluetooth.le.ScanCallback#onScanFailed(int)}
- */
- public void onScanFailed(int errorCode) {}
-
- /**
- * See
- * {@link android.bluetooth.le.ScanCallback#onScanResult(int, android.bluetooth.le.ScanResult)}.
- */
- public void onScanResult(int callbackType, ScanResult result) {}
-
- /**
- * See {@link
- * android.bluetooth.le.ScanCallback#onBatchScanResult(List)}.
- */
- public void onBatchScanResults(List results) {}
-
- /** Unwraps scan callback. */
- public android.bluetooth.le.ScanCallback unwrap() {
- return mWrappedScanCallback;
- }
-
- /** Forward callback to testable instance. */
- private class InternalScanCallback extends android.bluetooth.le.ScanCallback {
- @Override
- public void onScanFailed(int errorCode) {
- ScanCallback.this.onScanFailed(errorCode);
- }
-
- @Override
- public void onScanResult(int callbackType, android.bluetooth.le.ScanResult result) {
- ScanCallback.this.onScanResult(callbackType, ScanResult.wrap(result));
- }
-
- @Override
- public void onBatchScanResults(List results) {
- List wrappedScanResults = new ArrayList<>();
- for (android.bluetooth.le.ScanResult result : results) {
- wrappedScanResults.add(ScanResult.wrap(result));
- }
- ScanCallback.this.onBatchScanResults(wrappedScanResults);
- }
- }
-}
diff --git a/nearby/service/java/com/android/server/nearby/common/bluetooth/testability/android/bluetooth/le/ScanResult.java b/nearby/service/java/com/android/server/nearby/common/bluetooth/testability/android/bluetooth/le/ScanResult.java
deleted file mode 100644
index 1a6b7b304b6f72a1bbb7720701945ea8fae755d1..0000000000000000000000000000000000000000
--- a/nearby/service/java/com/android/server/nearby/common/bluetooth/testability/android/bluetooth/le/ScanResult.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.nearby.common.bluetooth.testability.android.bluetooth.le;
-
-import android.annotation.TargetApi;
-import android.bluetooth.le.ScanRecord;
-import android.os.Build;
-
-import com.android.server.nearby.common.bluetooth.testability.android.bluetooth.BluetoothDevice;
-
-import javax.annotation.Nullable;
-
-/**
- * Mockable wrapper of {@link android.bluetooth.le.ScanResult}.
- */
-@TargetApi(Build.VERSION_CODES.LOLLIPOP)
-public class ScanResult {
-
- private final android.bluetooth.le.ScanResult mWrappedScanResult;
-
- private ScanResult(android.bluetooth.le.ScanResult scanResult) {
- mWrappedScanResult = scanResult;
- }
-
- /** See {@link android.bluetooth.le.ScanResult#getScanRecord()}. */
- @Nullable
- public ScanRecord getScanRecord() {
- return mWrappedScanResult.getScanRecord();
- }
-
- /** See {@link android.bluetooth.le.ScanResult#getRssi()}. */
- public int getRssi() {
- return mWrappedScanResult.getRssi();
- }
-
- /** See {@link android.bluetooth.le.ScanResult#getTimestampNanos()}. */
- public long getTimestampNanos() {
- return mWrappedScanResult.getTimestampNanos();
- }
-
- /** See {@link android.bluetooth.le.ScanResult#getDevice()}. */
- public BluetoothDevice getDevice() {
- return BluetoothDevice.wrap(mWrappedScanResult.getDevice());
- }
-
- /** Creates a wrapper of scan result. */
- public static ScanResult wrap(android.bluetooth.le.ScanResult scanResult) {
- return new ScanResult(scanResult);
- }
-}
diff --git a/nearby/service/java/com/android/server/nearby/common/bluetooth/util/BluetoothGattUtils.java b/nearby/service/java/com/android/server/nearby/common/bluetooth/util/BluetoothGattUtils.java
deleted file mode 100644
index bb51920f18533fdda8c65e92774cb5c84f26a981..0000000000000000000000000000000000000000
--- a/nearby/service/java/com/android/server/nearby/common/bluetooth/util/BluetoothGattUtils.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.nearby.common.bluetooth.util;
-
-import android.bluetooth.BluetoothGatt;
-import android.bluetooth.BluetoothGattCharacteristic;
-import android.bluetooth.BluetoothGattDescriptor;
-import android.bluetooth.BluetoothGattService;
-
-import javax.annotation.Nullable;
-
-/**
- * Utils for Gatt profile.
- */
-public class BluetoothGattUtils {
-
- /**
- * Returns a string message for a BluetoothGatt status codes.
- */
- public static String getMessageForStatusCode(int statusCode) {
- switch (statusCode) {
- case BluetoothGatt.GATT_SUCCESS:
- return "GATT_SUCCESS";
- case BluetoothGatt.GATT_FAILURE:
- return "GATT_FAILURE";
- case BluetoothGatt.GATT_INSUFFICIENT_AUTHENTICATION:
- return "GATT_INSUFFICIENT_AUTHENTICATION";
- case BluetoothGatt.GATT_INSUFFICIENT_AUTHORIZATION:
- return "GATT_INSUFFICIENT_AUTHORIZATION";
- case BluetoothGatt.GATT_INSUFFICIENT_ENCRYPTION:
- return "GATT_INSUFFICIENT_ENCRYPTION";
- case BluetoothGatt.GATT_INVALID_ATTRIBUTE_LENGTH:
- return "GATT_INVALID_ATTRIBUTE_LENGTH";
- case BluetoothGatt.GATT_INVALID_OFFSET:
- return "GATT_INVALID_OFFSET";
- case BluetoothGatt.GATT_READ_NOT_PERMITTED:
- return "GATT_READ_NOT_PERMITTED";
- case BluetoothGatt.GATT_REQUEST_NOT_SUPPORTED:
- return "GATT_REQUEST_NOT_SUPPORTED";
- case BluetoothGatt.GATT_WRITE_NOT_PERMITTED:
- return "GATT_WRITE_NOT_PERMITTED";
- case BluetoothGatt.GATT_CONNECTION_CONGESTED:
- return "GATT_CONNECTION_CONGESTED";
- default:
- return "Unknown error code";
- }
- }
-
- /** Creates a user-readable string from a {@link BluetoothGattDescriptor}. */
- public static String toString(@Nullable BluetoothGattDescriptor descriptor) {
- if (descriptor == null) {
- return "null descriptor";
- }
- return String.format("descriptor %s on %s",
- descriptor.getUuid(),
- toString(descriptor.getCharacteristic()));
- }
-
- /** Creates a user-readable string from a {@link BluetoothGattCharacteristic}. */
- public static String toString(@Nullable BluetoothGattCharacteristic characteristic) {
- if (characteristic == null) {
- return "null characteristic";
- }
- return String.format("characteristic %s on %s",
- characteristic.getUuid(),
- toString(characteristic.getService()));
- }
-
- /** Creates a user-readable string from a {@link BluetoothGattService}. */
- public static String toString(@Nullable BluetoothGattService service) {
- if (service == null) {
- return "null service";
- }
- return String.format("service %s", service.getUuid());
- }
-}
diff --git a/nearby/service/java/com/android/server/nearby/common/bluetooth/util/BluetoothOperationExecutor.java b/nearby/service/java/com/android/server/nearby/common/bluetooth/util/BluetoothOperationExecutor.java
deleted file mode 100644
index fecf48362425a3375e52d67b043d61eb7bb55666..0000000000000000000000000000000000000000
--- a/nearby/service/java/com/android/server/nearby/common/bluetooth/util/BluetoothOperationExecutor.java
+++ /dev/null
@@ -1,548 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.nearby.common.bluetooth.util;
-
-import android.bluetooth.BluetoothGatt;
-import android.util.Log;
-
-import com.android.server.nearby.common.bluetooth.BluetoothException;
-import com.android.server.nearby.common.bluetooth.BluetoothGattException;
-import com.android.server.nearby.common.bluetooth.testability.NonnullProvider;
-import com.android.server.nearby.common.bluetooth.testability.TimeProvider;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Joiner;
-import com.google.common.base.Objects;
-
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Queue;
-import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Future;
-import java.util.concurrent.LinkedBlockingDeque;
-import java.util.concurrent.Semaphore;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
-
-import javax.annotation.Nullable;
-
-/**
- * Scheduler to coordinate parallel bluetooth operations.
- */
-public class BluetoothOperationExecutor {
-
- private static final String TAG = BluetoothOperationExecutor.class.getSimpleName();
-
- /**
- * Special value to indicate that the result is null (since {@link BlockingQueue} doesn't allow
- * null elements).
- */
- private static final Object NULL_RESULT = new Object();
-
- /**
- * Special value to indicate that there should be no timeout on the operation.
- */
- private static final long NO_TIMEOUT = -1;
-
- private final NonnullProvider> mBlockingQueueProvider;
- private final TimeProvider mTimeProvider;
- @VisibleForTesting
- final Map, Queue