1 /* 2 * Copyright (C) 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.fastpair.pairinghandler; 18 19 import static com.android.server.nearby.common.bluetooth.fastpair.BluetoothAddress.maskBluetoothAddress; 20 import static com.android.server.nearby.fastpair.FastPairManager.isThroughFastPair2InitialPairing; 21 22 import android.annotation.Nullable; 23 import android.bluetooth.BluetoothDevice; 24 import android.content.Context; 25 import android.util.Log; 26 27 import com.android.server.nearby.common.bluetooth.fastpair.FastPairConnection; 28 import com.android.server.nearby.common.bluetooth.fastpair.Preferences; 29 import com.android.server.nearby.fastpair.cache.DiscoveryItem; 30 import com.android.server.nearby.fastpair.footprint.FootprintsDeviceManager; 31 import com.android.server.nearby.fastpair.halfsheet.FastPairHalfSheetManager; 32 import com.android.server.nearby.fastpair.notification.FastPairNotificationManager; 33 import com.android.server.nearby.intdefs.FastPairEventIntDefs; 34 35 /** Base class for pairing progress handler. */ 36 public abstract class PairingProgressHandlerBase { 37 protected final Context mContext; 38 protected final DiscoveryItem mItem; 39 @Nullable 40 private FastPairEventIntDefs.ErrorCode mRescueFromError; 41 getPairStartEventCode()42 protected abstract int getPairStartEventCode(); 43 getPairEndEventCode()44 protected abstract int getPairEndEventCode(); 45 PairingProgressHandlerBase(Context context, DiscoveryItem item)46 protected PairingProgressHandlerBase(Context context, DiscoveryItem item) { 47 this.mContext = context; 48 this.mItem = item; 49 } 50 51 52 /** 53 * Pairing progress init function. 54 */ create( Context context, DiscoveryItem item, @Nullable String companionApp, @Nullable byte[] accountKey, FootprintsDeviceManager footprints, FastPairNotificationManager notificationManager, FastPairHalfSheetManager fastPairHalfSheetManager, boolean isRetroactivePair)55 public static PairingProgressHandlerBase create( 56 Context context, 57 DiscoveryItem item, 58 @Nullable String companionApp, 59 @Nullable byte[] accountKey, 60 FootprintsDeviceManager footprints, 61 FastPairNotificationManager notificationManager, 62 FastPairHalfSheetManager fastPairHalfSheetManager, 63 boolean isRetroactivePair) { 64 PairingProgressHandlerBase pairingProgressHandlerBase; 65 // Disable half sheet on subsequent pairing 66 if (item.getAuthenticationPublicKeySecp256R1() != null 67 && accountKey != null) { 68 // Subsequent pairing 69 pairingProgressHandlerBase = 70 new NotificationPairingProgressHandler( 71 context, item, companionApp, accountKey, notificationManager); 72 } else { 73 pairingProgressHandlerBase = 74 new HalfSheetPairingProgressHandler(context, item, companionApp, accountKey); 75 } 76 77 78 Log.v("PairingHandler", 79 "PairingProgressHandler:Create " 80 + item.getMacAddress() + " for pairing"); 81 return pairingProgressHandlerBase; 82 } 83 84 85 /** 86 * Function calls when pairing start. 87 */ onPairingStarted()88 public void onPairingStarted() { 89 Log.v("PairingHandler", "PairingProgressHandler:onPairingStarted"); 90 } 91 92 /** 93 * Waits for screen to unlock. 94 */ onWaitForScreenUnlock()95 public void onWaitForScreenUnlock() { 96 Log.v("PairingHandler", "PairingProgressHandler:onWaitForScreenUnlock"); 97 } 98 99 /** 100 * Function calls when screen unlock. 101 */ onScreenUnlocked()102 public void onScreenUnlocked() { 103 Log.v("PairingHandler", "PairingProgressHandler:onScreenUnlocked"); 104 } 105 106 /** 107 * Calls when the handler is ready to pair. 108 */ onReadyToPair()109 public void onReadyToPair() { 110 Log.v("PairingHandler", "PairingProgressHandler:onReadyToPair"); 111 } 112 113 /** 114 * Helps to set up pairing preference. 115 */ onSetupPreferencesBuilder(Preferences.Builder builder)116 public void onSetupPreferencesBuilder(Preferences.Builder builder) { 117 Log.v("PairingHandler", "PairingProgressHandler:onSetupPreferencesBuilder"); 118 } 119 120 /** 121 * Calls when pairing setup complete. 122 */ onPairingSetupCompleted()123 public void onPairingSetupCompleted() { 124 Log.v("PairingHandler", "PairingProgressHandler:onPairingSetupCompleted"); 125 } 126 127 /** Called while pairing if needs to handle the passkey confirmation by Ui. */ onHandlePasskeyConfirmation(BluetoothDevice device, int passkey)128 public void onHandlePasskeyConfirmation(BluetoothDevice device, int passkey) { 129 Log.v("PairingHandler", "PairingProgressHandler:onHandlePasskeyConfirmation"); 130 } 131 132 /** 133 * In this callback, we know if it is a real initial pairing by existing account key, and do 134 * following things: 135 * <li>1, optIn footprint for initial pairing. 136 * <li>2, write the device name to provider 137 * <li>2.1, generate default personalized name for initial pairing or get the personalized name 138 * from footprint for subsequent pairing. 139 * <li>2.2, set alias name for the bluetooth device. 140 * <li>2.3, update the device name for connection to write into provider for initial pair. 141 * <li>3, suppress battery notifications until oobe finishes. 142 * 143 * @return display name of the pairing device 144 */ 145 @Nullable onPairedCallbackCalled( FastPairConnection connection, byte[] accountKey, FootprintsDeviceManager footprints, String address)146 public String onPairedCallbackCalled( 147 FastPairConnection connection, 148 byte[] accountKey, 149 FootprintsDeviceManager footprints, 150 String address) { 151 Log.v("PairingHandler", 152 "PairingProgressHandler:onPairedCallbackCalled with address: " 153 + address); 154 155 byte[] existingAccountKey = connection.getExistingAccountKey(); 156 optInFootprintsForInitialPairing(footprints, mItem, accountKey, existingAccountKey); 157 // Add support for naming the device 158 return null; 159 } 160 161 /** 162 * Gets the related info from db use account key. 163 */ 164 @Nullable getKeyForLocalCache( byte[] accountKey, FastPairConnection connection, FastPairConnection.SharedSecret sharedSecret)165 public byte[] getKeyForLocalCache( 166 byte[] accountKey, FastPairConnection connection, 167 FastPairConnection.SharedSecret sharedSecret) { 168 Log.v("PairingHandler", "PairingProgressHandler:getKeyForLocalCache"); 169 return accountKey != null ? accountKey : connection.getExistingAccountKey(); 170 } 171 172 /** 173 * Function handles pairing fail. 174 */ onPairingFailed(Throwable throwable)175 public void onPairingFailed(Throwable throwable) { 176 Log.w("PairingHandler", "PairingProgressHandler:onPairingFailed"); 177 } 178 179 /** 180 * Function handles pairing success. 181 */ onPairingSuccess(String address)182 public void onPairingSuccess(String address) { 183 Log.v("PairingHandler", "PairingProgressHandler:onPairingSuccess with address: " 184 + maskBluetoothAddress(address)); 185 } 186 optInFootprintsForInitialPairing( FootprintsDeviceManager footprints, DiscoveryItem item, byte[] accountKey, @Nullable byte[] existingAccountKey)187 private static void optInFootprintsForInitialPairing( 188 FootprintsDeviceManager footprints, 189 DiscoveryItem item, 190 byte[] accountKey, 191 @Nullable byte[] existingAccountKey) { 192 if (isThroughFastPair2InitialPairing(item, accountKey) && existingAccountKey == null) { 193 // enable the save to footprint 194 Log.v("PairingHandler", "footprint should call opt in here"); 195 } 196 } 197 198 /** 199 * Returns {@code true} if the PairingProgressHandler is running at the background. 200 * 201 * <p>In order to keep the following status notification shows as a heads up, we must wait for 202 * the screen unlocked to continue. 203 */ skipWaitingScreenUnlock()204 public boolean skipWaitingScreenUnlock() { 205 return false; 206 } 207 } 208 209