• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2021 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server.nearby.common.bluetooth.fastpair;
18 
19 import android.annotation.WorkerThread;
20 import android.bluetooth.BluetoothDevice;
21 
22 import androidx.annotation.Nullable;
23 import androidx.core.util.Consumer;
24 
25 import com.android.internal.annotations.VisibleForTesting;
26 import com.android.server.nearby.common.bluetooth.BluetoothException;
27 
28 import java.security.GeneralSecurityException;
29 import java.util.Arrays;
30 import java.util.List;
31 import java.util.Objects;
32 import java.util.concurrent.ExecutionException;
33 import java.util.concurrent.TimeoutException;
34 
35 /** Abstract class for pairing or connecting via FastPair. */
36 public abstract class FastPairConnection {
37     @Nullable protected OnPairedCallback mPairedCallback;
38     @Nullable protected OnGetBluetoothAddressCallback mOnGetBluetoothAddressCallback;
39     @Nullable protected PasskeyConfirmationHandler mPasskeyConfirmationHandler;
40     @Nullable protected FastPairSignalChecker mFastPairSignalChecker;
41     @Nullable protected Consumer<Integer> mRescueFromError;
42     @Nullable protected Runnable mPrepareCreateBondCallback;
43     protected boolean mPasskeyIsGotten;
44 
45     /** Sets a callback to be invoked once the device is paired. */
setOnPairedCallback(OnPairedCallback callback)46     public void setOnPairedCallback(OnPairedCallback callback) {
47         this.mPairedCallback = callback;
48     }
49 
50     /** Sets a callback to be invoked while the target bluetooth address is decided. */
setOnGetBluetoothAddressCallback(OnGetBluetoothAddressCallback callback)51     public void setOnGetBluetoothAddressCallback(OnGetBluetoothAddressCallback callback) {
52         this.mOnGetBluetoothAddressCallback = callback;
53     }
54 
55     /** Sets a callback to be invoked while handling the passkey confirmation. */
setPasskeyConfirmationHandler( PasskeyConfirmationHandler passkeyConfirmationHandler)56     public void setPasskeyConfirmationHandler(
57             PasskeyConfirmationHandler passkeyConfirmationHandler) {
58         this.mPasskeyConfirmationHandler = passkeyConfirmationHandler;
59     }
60 
setFastPairSignalChecker(FastPairSignalChecker fastPairSignalChecker)61     public void setFastPairSignalChecker(FastPairSignalChecker fastPairSignalChecker) {
62         this.mFastPairSignalChecker = fastPairSignalChecker;
63     }
64 
setRescueFromError(Consumer<Integer> rescueFromError)65     public void setRescueFromError(Consumer<Integer> rescueFromError) {
66         this.mRescueFromError = rescueFromError;
67     }
68 
setPrepareCreateBondCallback(Runnable runnable)69     public void setPrepareCreateBondCallback(Runnable runnable) {
70         this.mPrepareCreateBondCallback = runnable;
71     }
72 
73     @VisibleForTesting
74     @Nullable
getPrepareCreateBondCallback()75     public Runnable getPrepareCreateBondCallback() {
76         return mPrepareCreateBondCallback;
77     }
78 
79     /**
80      * Sets the fast pair history for identifying whether or not the provider has paired with the
81      * primary account on other phones before.
82      */
83     @WorkerThread
setFastPairHistory(List<FastPairHistoryItem> fastPairHistoryItem)84     public abstract void setFastPairHistory(List<FastPairHistoryItem> fastPairHistoryItem);
85 
86     /** Sets the device name to the Provider. */
setProviderDeviceName(String deviceName)87     public abstract void setProviderDeviceName(String deviceName);
88 
89     /** Gets the device name from the Provider. */
90     @Nullable
getProviderDeviceName()91     public abstract String getProviderDeviceName();
92 
93     /**
94      * Gets the existing account key of the Provider.
95      *
96      * @return the existing account key if the Provider has paired with the account, null otherwise
97      */
98     @WorkerThread
99     @Nullable
getExistingAccountKey()100     public abstract byte[] getExistingAccountKey();
101 
102     /**
103      * Pairs with Provider. Synchronous: Blocks until paired and connected. Throws on any error.
104      *
105      * @return the secret key for the user's account, if written
106      */
107     @WorkerThread
108     @Nullable
pair()109     public abstract SharedSecret pair()
110             throws BluetoothException, InterruptedException, TimeoutException, ExecutionException,
111             PairingException, ReflectionException;
112 
113     /**
114      * Pairs with Provider. Synchronous: Blocks until paired and connected. Throws on any error.
115      *
116      * @param key can be in two different formats. If it is 16 bytes long, then it is an AES account
117      *    key. Otherwise, it's a public key generated by {@link EllipticCurveDiffieHellmanExchange}.
118      *    See go/fast-pair-2-spec for how each of these keys are used.
119      * @return the secret key for the user's account, if written
120      */
121     @WorkerThread
122     @Nullable
pair(@ullable byte[] key)123     public abstract SharedSecret pair(@Nullable byte[] key)
124             throws BluetoothException, InterruptedException, TimeoutException, ExecutionException,
125             PairingException, GeneralSecurityException, ReflectionException;
126 
127     /** Unpairs with Provider. Synchronous: Blocks until unpaired. Throws on any error. */
128     @WorkerThread
unpair(BluetoothDevice device)129     public abstract void unpair(BluetoothDevice device)
130             throws InterruptedException, TimeoutException, ExecutionException, PairingException,
131             ReflectionException;
132 
133     /** Gets the public address of the Provider. */
134     @Nullable
getPublicAddress()135     public abstract String getPublicAddress();
136 
137 
138     /** Callback for getting notifications when pairing has completed. */
139     public interface OnPairedCallback {
140         /** Called when the device at address has finished pairing. */
onPaired(String address)141         void onPaired(String address);
142     }
143 
144     /** Callback for getting bluetooth address Bisto oobe need this information */
145     public interface OnGetBluetoothAddressCallback {
146         /** Called when the device has received bluetooth address. */
onGetBluetoothAddress(String address)147         void onGetBluetoothAddress(String address);
148     }
149 
150     /** Holds the exchanged secret key and the public mac address of the device. */
151     public static class SharedSecret {
152         private final byte[] mKey;
153         private final String mAddress;
SharedSecret(byte[] key, String address)154         private SharedSecret(byte[] key, String address) {
155             mKey = key;
156             mAddress = address;
157         }
158 
159         /** Creates Shared Secret. */
create(byte[] key, String address)160         public static SharedSecret create(byte[] key, String address) {
161             return new SharedSecret(key, address);
162         }
163 
164         /** Gets Shared Secret Key. */
getKey()165         public byte[] getKey() {
166             return mKey;
167         }
168 
169         /** Gets Shared Secret Address. */
getAddress()170         public String getAddress() {
171             return mAddress;
172         }
173 
174         @Override
toString()175         public String toString() {
176             return "SharedSecret{"
177                     + "key=" + Arrays.toString(mKey) + ", "
178                     + "address=" + mAddress
179                     + "}";
180         }
181 
182         @Override
equals(@ullable Object o)183         public boolean equals(@Nullable Object o) {
184             if (o == this) {
185                 return true;
186             }
187             if (o instanceof SharedSecret) {
188                 SharedSecret that = (SharedSecret) o;
189                 return Arrays.equals(this.mKey, that.getKey())
190                         && this.mAddress.equals(that.getAddress());
191             }
192             return false;
193         }
194 
195         @Override
hashCode()196         public int hashCode() {
197             return Objects.hash(Arrays.hashCode(mKey), mAddress);
198         }
199     }
200 
201     /** Invokes if gotten the passkey. */
setPasskeyIsGotten()202     public void setPasskeyIsGotten() {
203         mPasskeyIsGotten = true;
204     }
205 
206     /** Returns the value of passkeyIsGotten. */
getPasskeyIsGotten()207     public boolean getPasskeyIsGotten() {
208         return mPasskeyIsGotten;
209     }
210 
211     /** Interface to get latest address of ModelId. */
212     public interface FastPairSignalChecker {
213         /** Gets address of ModelId. */
getValidAddressForModelId(String currentDevice)214         String getValidAddressForModelId(String currentDevice);
215     }
216 }
217