Merge "Add subsequent related db save info after pairing success" into tm-dev
diff --git a/nearby/service/java/com/android/server/nearby/fastpair/FastPairAdvHandler.java b/nearby/service/java/com/android/server/nearby/fastpair/FastPairAdvHandler.java
index 08e98db..4ee16b7 100644
--- a/nearby/service/java/com/android/server/nearby/fastpair/FastPairAdvHandler.java
+++ b/nearby/service/java/com/android/server/nearby/fastpair/FastPairAdvHandler.java
@@ -27,17 +27,19 @@
import android.nearby.NearbyDevice;
import android.util.Log;
+import com.android.server.nearby.common.ble.decode.FastPairDecoder;
import com.android.server.nearby.common.bloomfilter.BloomFilter;
import com.android.server.nearby.common.bloomfilter.FastPairBloomFilterHasher;
import com.android.server.nearby.common.locator.Locator;
+import com.android.server.nearby.fastpair.cache.FastPairCacheManager;
import com.android.server.nearby.fastpair.halfsheet.FastPairHalfSheetManager;
import com.android.server.nearby.provider.FastPairDataProvider;
import com.android.server.nearby.util.DataUtils;
-import com.android.server.nearby.util.FastPairDecoder;
import com.android.server.nearby.util.Hex;
import java.util.List;
+import service.proto.Cache;
import service.proto.Data;
import service.proto.Rpcs;
@@ -47,6 +49,7 @@
public class FastPairAdvHandler {
Context mContext;
String mBleAddress;
+
/** The types about how the bloomfilter is processed. */
public enum ProcessBloomFilterType {
IGNORE, // The bloomfilter is not handled. e.g. distance is too far away.
@@ -69,16 +72,18 @@
public void handleBroadcast(NearbyDevice device) {
FastPairDevice fastPairDevice = (FastPairDevice) device;
mBleAddress = fastPairDevice.getBluetoothAddress();
- List<Account> accountList =
- FastPairDataProvider.getInstance().loadFastPairEligibleAccounts();
+ FastPairDataProvider dataProvider = FastPairDataProvider.getInstance();
+ if (dataProvider == null) {
+ return;
+ }
+ List<Account> accountList = dataProvider.loadFastPairEligibleAccounts();
if (FastPairDecoder.checkModelId(fastPairDevice.getData())) {
byte[] model = FastPairDecoder.getModelId(fastPairDevice.getData());
Log.d(TAG, "On discovery model id " + Hex.bytesToStringLowercase(model));
// Use api to get anti spoofing key from model id.
try {
Rpcs.GetObservedDeviceResponse response =
- FastPairDataProvider.getInstance()
- .loadFastPairAntispoofkeyDeviceMetadata(model);
+ dataProvider.loadFastPairAntispoofkeyDeviceMetadata(model);
if (response == null) {
Log.e(TAG, "server does not have model id "
+ Hex.bytesToStringLowercase(model));
@@ -94,26 +99,41 @@
} else {
// Start to process bloom filter
try {
- Log.d(TAG, "account list size " + accountList.size());
byte[] bloomFilterByteArray = FastPairDecoder
.getBloomFilter(fastPairDevice.getData());
byte[] bloomFilterSalt = FastPairDecoder
.getBloomFilterSalt(fastPairDevice.getData());
if (bloomFilterByteArray == null || bloomFilterByteArray.length == 0) {
- Log.d(TAG, "bloom filter byte size is 0");
return;
}
for (Account account : accountList) {
List<Data.FastPairDeviceWithAccountKey> listDevices =
- FastPairDataProvider.getInstance()
- .loadFastPairDeviceWithAccountKey(account);
+ dataProvider.loadFastPairDeviceWithAccountKey(account);
Data.FastPairDeviceWithAccountKey recognizedDevice =
findRecognizedDevice(listDevices,
new BloomFilter(bloomFilterByteArray,
new FastPairBloomFilterHasher()), bloomFilterSalt);
+
if (recognizedDevice != null) {
Log.d(TAG, "find matched device show notification to remind"
+ " user to pair");
+ // Check if the device is already paired
+ List<Cache.StoredFastPairItem> storedFastPairItemList =
+ Locator.get(mContext, FastPairCacheManager.class)
+ .getAllSavedStoredFastPairItem();
+ Cache.StoredFastPairItem recognizedStoredFastPairItem =
+ findRecognizedDeviceFromCachedItem(storedFastPairItemList,
+ new BloomFilter(bloomFilterByteArray,
+ new FastPairBloomFilterHasher()), bloomFilterSalt);
+ if (recognizedStoredFastPairItem != null) {
+ // The bloomfilter is recognized in the cache so the device is paired
+ // before
+ Log.d(TAG, "bloom filter is recognized in the cache");
+ continue;
+ } else {
+ Log.d(TAG, "bloom filter is not recognized not paired before");
+ }
+
return;
}
}
@@ -132,10 +152,27 @@
@Nullable
static Data.FastPairDeviceWithAccountKey findRecognizedDevice(
List<Data.FastPairDeviceWithAccountKey> devices, BloomFilter bloomFilter, byte[] salt) {
+ Log.d(TAG, "saved devices size in the account is " + devices.size());
for (Data.FastPairDeviceWithAccountKey device : devices) {
- if (device.getAccountKey().toByteArray() == null) {
- continue;
+ byte[] rotatedKey = concat(device.getAccountKey().toByteArray(), salt);
+ StringBuilder sb = new StringBuilder();
+ for (byte b : rotatedKey) {
+ sb.append(b);
}
+ if (bloomFilter.possiblyContains(rotatedKey)) {
+ Log.d(TAG, "match " + sb.toString());
+ return device;
+ } else {
+ Log.d(TAG, "not match " + sb.toString());
+ }
+ }
+ return null;
+ }
+
+ @Nullable
+ static Cache.StoredFastPairItem findRecognizedDeviceFromCachedItem(
+ List<Cache.StoredFastPairItem> devices, BloomFilter bloomFilter, byte[] salt) {
+ for (Cache.StoredFastPairItem device : devices) {
byte[] rotatedKey = concat(device.getAccountKey().toByteArray(), salt);
if (bloomFilter.possiblyContains(rotatedKey)) {
return device;
@@ -143,4 +180,5 @@
}
return null;
}
+
}
diff --git a/nearby/service/java/com/android/server/nearby/fastpair/FastPairController.java b/nearby/service/java/com/android/server/nearby/fastpair/FastPairController.java
index 1264ade..896056b 100644
--- a/nearby/service/java/com/android/server/nearby/fastpair/FastPairController.java
+++ b/nearby/service/java/com/android/server/nearby/fastpair/FastPairController.java
@@ -237,12 +237,14 @@
ByteString.copyFrom(hashValue));
// account data place holder here
try {
- List<Account> accountList =
- FastPairDataProvider.getInstance().loadFastPairEligibleAccounts();
+ FastPairDataProvider fastPairDataProvider = FastPairDataProvider.getInstance();
+ if (fastPairDataProvider == null) {
+ return;
+ }
+ List<Account> accountList = fastPairDataProvider.loadFastPairEligibleAccounts();
if (accountList.size() > 0) {
- FastPairDataProvider.getInstance().optIn(accountList.get(0));
- FastPairDataProvider.getInstance().upload(
- accountList.get(0), uploadInfo);
+ fastPairDataProvider.optIn(accountList.get(0));
+ fastPairDataProvider.upload(accountList.get(0), uploadInfo);
}
} catch (IllegalStateException e) {
Log.e(TAG, "OEM does not construct fast pair data proxy correctly");
diff --git a/nearby/service/java/com/android/server/nearby/fastpair/FastPairManager.java b/nearby/service/java/com/android/server/nearby/fastpair/FastPairManager.java
index 04f72f0..cb4e6cb 100644
--- a/nearby/service/java/com/android/server/nearby/fastpair/FastPairManager.java
+++ b/nearby/service/java/com/android/server/nearby/fastpair/FastPairManager.java
@@ -41,6 +41,7 @@
import androidx.annotation.NonNull;
+import com.android.server.nearby.common.ble.decode.FastPairDecoder;
import com.android.server.nearby.common.bluetooth.BluetoothException;
import com.android.server.nearby.common.bluetooth.fastpair.FastPairConnection;
import com.android.server.nearby.common.bluetooth.fastpair.FastPairDualConnection;
@@ -48,6 +49,7 @@
import com.android.server.nearby.common.bluetooth.fastpair.Preferences;
import com.android.server.nearby.common.bluetooth.fastpair.ReflectionException;
import com.android.server.nearby.common.bluetooth.fastpair.SimpleBroadcastReceiver;
+import com.android.server.nearby.common.bluetooth.testability.android.bluetooth.BluetoothDevice;
import com.android.server.nearby.common.eventloop.Annotations;
import com.android.server.nearby.common.eventloop.EventLoop;
import com.android.server.nearby.common.eventloop.NamedRunnable;
@@ -58,10 +60,12 @@
import com.android.server.nearby.fastpair.footprint.FootprintsDeviceManager;
import com.android.server.nearby.fastpair.halfsheet.FastPairHalfSheetManager;
import com.android.server.nearby.fastpair.pairinghandler.PairingProgressHandlerBase;
-import com.android.server.nearby.util.FastPairDecoder;
import com.android.server.nearby.util.ForegroundThread;
import com.android.server.nearby.util.Hex;
+import com.google.common.collect.ImmutableList;
+import com.google.protobuf.ByteString;
+
import java.security.GeneralSecurityException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
@@ -71,6 +75,7 @@
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
+import service.proto.Cache;
import service.proto.Rpcs;
/**
@@ -180,7 +185,6 @@
@Nullable String companionApp,
FootprintsDeviceManager footprints,
PairingProgressHandlerBase pairingProgressHandlerBase) {
-
return executor.submit(
() -> pairInternal(context, item, companionApp, accountKey, footprints,
pairingProgressHandlerBase), /* result= */ null);
@@ -197,7 +201,8 @@
@Nullable byte[] accountKey,
FootprintsDeviceManager footprints,
PairingProgressHandlerBase pairingProgressHandlerBase) {
- FastPairHalfSheetManager manager = Locator.get(context, FastPairHalfSheetManager.class);
+ FastPairHalfSheetManager fastPairHalfSheetManager =
+ Locator.get(context, FastPairHalfSheetManager.class);
try {
pairingProgressHandlerBase.onPairingStarted();
if (pairingProgressHandlerBase.skipWaitingScreenUnlock()) {
@@ -268,24 +273,17 @@
if (sharedSecret != null) {
Locator.get(context, FastPairController.class).addDeviceToFootprint(
connection.getPublicAddress(), sharedSecret.getKey(), item);
+ cacheFastPairDevice(context, connection.getPublicAddress(),
+ sharedSecret.getKey(), item);
}
}
-
- byte[] key = pairingProgressHandlerBase.getKeyForLocalCache(accountKey,
- connection, sharedSecret);
-
- // We don't cache initial pairing case here but cache it when upload to footprints.
- if (key != null) {
- // CacheManager to save the content here
- }
} else {
// Fast Pair one
connection.pair();
}
-
// TODO(b/213373051): Merge logic with pairingProgressHandlerBase or delete the
// pairingProgressHandlerBase class.
- manager.showPairingSuccessHalfSheet(connection.getPublicAddress());
+ fastPairHalfSheetManager.showPairingSuccessHalfSheet(connection.getPublicAddress());
pairingProgressHandlerBase.onPairingSuccess(connection.getPublicAddress());
} catch (BluetoothException
| InterruptedException
@@ -298,11 +296,38 @@
// TODO(b/213373051): Merge logic with pairingProgressHandlerBase or delete the
// pairingProgressHandlerBase class.
- manager.showPairingFailed();
+ fastPairHalfSheetManager.showPairingFailed();
pairingProgressHandlerBase.onPairingFailed(e);
}
}
+ private static void cacheFastPairDevice(Context context, String publicAddress, byte[] key,
+ DiscoveryItem item) {
+ try {
+ Locator.get(context, EventLoop.class).postAndWait(
+ new NamedRunnable("FastPairCacheDevice") {
+ @Override
+ public void run() {
+ Cache.StoredFastPairItem storedFastPairItem =
+ Cache.StoredFastPairItem.newBuilder()
+ .setMacAddress(publicAddress)
+ .setAccountKey(ByteString.copyFrom(key))
+ .setModelId(item.getTriggerId())
+ .addAllFeatures(item.getFastPairInformation() == null
+ ? ImmutableList.of() :
+ item.getFastPairInformation().getFeaturesList())
+ .setDiscoveryItem(item.getCopyOfStoredItem())
+ .build();
+ Locator.get(context, FastPairCacheManager.class)
+ .putStoredFastPairItem(storedFastPairItem);
+ }
+ }
+ );
+ } catch (InterruptedException e) {
+ Log.e(TAG, "Fail to insert paired device into cache");
+ }
+ }
+
/** Checks if the pairing is initial pairing with fast pair 2.0 design. */
public static boolean isThroughFastPair2InitialPairing(
DiscoveryItem item, @Nullable byte[] accountKey) {
@@ -319,7 +344,7 @@
// regardless.
if (keyguardManager.isKeyguardLocked()) {
Log.v(TAG, "FastPair: Screen is locked, waiting until unlocked "
- + "to show status notifications.");
+ + "to show status notifications.");
try (SimpleBroadcastReceiver isUnlockedReceiver =
SimpleBroadcastReceiver.oneShotReceiver(
context, FlagUtils.getPreferencesBuilder().build(),
@@ -346,7 +371,7 @@
Settings.Secure.getUriFor(Settings.Secure.FAST_PAIR_SCAN_ENABLED),
/* notifyForDescendants= */ false,
mFastPairScanChangeContentObserver);
- } catch (SecurityException e) {
+ } catch (SecurityException e) {
Log.e(TAG, "Failed to register content observer for fast pair scan.", e);
}
}
@@ -395,7 +420,7 @@
}
/**
- * Starts or stops scanning according to mAllowScan value.
+ * Starts or stops scanning according to mAllowScan value.
*/
private void invalidateScan() {
NearbyManager nearbyManager = getNearbyManager();
@@ -415,6 +440,30 @@
}
/**
+ * When certain device is forgotten we need to remove the info from database because the info
+ * is no longer useful.
+ */
+ private void processBluetoothConnectionEvent(Intent intent) {
+ int bondState = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE,
+ BluetoothDevice.ERROR);
+ if (bondState == BluetoothDevice.BOND_NONE) {
+ BluetoothDevice device =
+ intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
+ if (device != null) {
+ Log.d("FastPairService", "Forget device detect");
+ processBackgroundTask(new Runnable() {
+ @Override
+ public void run() {
+ mLocatorContextWrapper.getLocator().get(FastPairCacheManager.class)
+ .removeStoredFastPairItem(device.getAddress());
+ }
+ });
+ }
+
+ }
+ }
+
+ /**
* Helper function to get bluetooth adapter.
*/
@Nullable
diff --git a/nearby/service/java/com/android/server/nearby/fastpair/cache/DiscoveryItemDbHelper.java b/nearby/service/java/com/android/server/nearby/fastpair/cache/DiscoveryItemDbHelper.java
deleted file mode 100644
index e171462..0000000
--- a/nearby/service/java/com/android/server/nearby/fastpair/cache/DiscoveryItemDbHelper.java
+++ /dev/null
@@ -1,60 +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.fastpair.cache;
-
-import android.content.Context;
-import android.database.sqlite.SQLiteDatabase;
-import android.database.sqlite.SQLiteOpenHelper;
-
-/**
- * Discovery db helper
- */
-public class DiscoveryItemDbHelper extends SQLiteOpenHelper {
-
- public static final int DATABASE_VERSION = 1;
- public static final String DATABASE_NAME = "ScanResult.db";
- private static final String SQL_CREATE_DB =
- "CREATE TABLE " + DiscoveryItemContract.DiscoveryItemEntry.TABLE_NAME
- + " (" + DiscoveryItemContract.DiscoveryItemEntry._ID
- + "INTEGER PRIMARY KEY,"
- + DiscoveryItemContract.DiscoveryItemEntry.COLUMN_MODEL_ID
- + " TEXT," + DiscoveryItemContract.DiscoveryItemEntry.COLUMN_SCAN_BYTE
- + " BLOB)";
- private static final String SQL_DELETE_DB =
- "DROP TABLE IF EXISTS " + DiscoveryItemContract.DiscoveryItemEntry.TABLE_NAME;
-
- public DiscoveryItemDbHelper(Context context) {
- super(context, DATABASE_NAME, null, DATABASE_VERSION);
- }
-
- @Override
- public void onCreate(SQLiteDatabase db) {
- db.execSQL(SQL_CREATE_DB);
- }
-
- @Override
- public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
- // Since the outdated data has no value so just remove the data.
- db.execSQL(SQL_DELETE_DB);
- onCreate(db);
- }
-
- @Override
- public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
- super.onDowngrade(db, oldVersion, newVersion);
- }
-}
diff --git a/nearby/service/java/com/android/server/nearby/fastpair/cache/FastPairCacheManager.java b/nearby/service/java/com/android/server/nearby/fastpair/cache/FastPairCacheManager.java
index fb2adb2..b840091 100644
--- a/nearby/service/java/com/android/server/nearby/fastpair/cache/FastPairCacheManager.java
+++ b/nearby/service/java/com/android/server/nearby/fastpair/cache/FastPairCacheManager.java
@@ -39,18 +39,18 @@
*/
public class FastPairCacheManager {
private final Context mContext;
- private final DiscoveryItemDbHelper mDiscoveryItemDbHelper;
+ private final FastPairDbHelper mFastPairDbHelper;
public FastPairCacheManager(Context context) {
mContext = context;
- mDiscoveryItemDbHelper = new DiscoveryItemDbHelper(context);
+ mFastPairDbHelper = new FastPairDbHelper(context);
}
/**
* Clean up function to release db
*/
public void cleanUp() {
- mDiscoveryItemDbHelper.close();
+ mFastPairDbHelper.close();
}
/**
@@ -74,10 +74,12 @@
}
/**
- * Save discovery item into database.
+ * Save discovery item into database. Discovery item is item that discovered through Ble before
+ * pairing success.
*/
public boolean saveDiscoveryItem(DiscoveryItem item) {
- SQLiteDatabase db = mDiscoveryItemDbHelper.getWritableDatabase();
+
+ SQLiteDatabase db = mFastPairDbHelper.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(DiscoveryItemContract.DiscoveryItemEntry.COLUMN_MODEL_ID, item.getTriggerId());
values.put(DiscoveryItemContract.DiscoveryItemEntry.COLUMN_SCAN_BYTE,
@@ -103,8 +105,7 @@
* Get discovery item from item id.
*/
public Cache.StoredDiscoveryItem getStoredDiscoveryItem(String itemId) {
-
- SQLiteDatabase db = mDiscoveryItemDbHelper.getReadableDatabase();
+ SQLiteDatabase db = mFastPairDbHelper.getReadableDatabase();
String[] projection = {
DiscoveryItemContract.DiscoveryItemEntry.COLUMN_MODEL_ID,
DiscoveryItemContract.DiscoveryItemEntry.COLUMN_SCAN_BYTE
@@ -140,7 +141,7 @@
*/
public List<Cache.StoredDiscoveryItem> getAllSavedStoreDiscoveryItem() {
List<Cache.StoredDiscoveryItem> storedDiscoveryItemList = new ArrayList<>();
- SQLiteDatabase db = mDiscoveryItemDbHelper.getReadableDatabase();
+ SQLiteDatabase db = mFastPairDbHelper.getReadableDatabase();
String[] projection = {
DiscoveryItemContract.DiscoveryItemEntry.COLUMN_MODEL_ID,
DiscoveryItemContract.DiscoveryItemEntry.COLUMN_SCAN_BYTE
@@ -169,6 +170,7 @@
cursor.close();
return storedDiscoveryItemList;
}
+
/**
* Get scan result from local database use model id
*/
@@ -176,4 +178,105 @@
return Cache.StoredScanResult.getDefaultInstance();
}
+ /**
+ * Gets the paired Fast Pair item that paired to the phone through mac address.
+ */
+ public Cache.StoredFastPairItem getStoredFastPairItemFromMacAddress(String macAddress) {
+ SQLiteDatabase db = mFastPairDbHelper.getReadableDatabase();
+ String[] projection = {
+ StoredFastPairItemContract.StoredFastPairItemEntry.COLUMN_ACCOUNT_KEY,
+ StoredFastPairItemContract.StoredFastPairItemEntry.COLUMN_MAC_ADDRESS,
+ StoredFastPairItemContract.StoredFastPairItemEntry.COLUMN_STORED_FAST_PAIR_BYTE
+ };
+ String selection =
+ StoredFastPairItemContract.StoredFastPairItemEntry.COLUMN_MAC_ADDRESS + " =? ";
+ String[] selectionArgs = {macAddress};
+ Cursor cursor = db.query(
+ StoredFastPairItemContract.StoredFastPairItemEntry.TABLE_NAME,
+ projection,
+ selection,
+ selectionArgs,
+ null,
+ null,
+ null
+ );
+
+ if (cursor.moveToNext()) {
+ byte[] res = cursor.getBlob(cursor.getColumnIndexOrThrow(
+ StoredFastPairItemContract.StoredFastPairItemEntry
+ .COLUMN_STORED_FAST_PAIR_BYTE));
+ try {
+ Cache.StoredFastPairItem item = Cache.StoredFastPairItem.parseFrom(res);
+ return item;
+ } catch (InvalidProtocolBufferException e) {
+ Log.e("FastPairCacheManager", "storediscovery has error");
+ }
+ }
+ cursor.close();
+ return Cache.StoredFastPairItem.getDefaultInstance();
+ }
+
+ /**
+ * Save paired fast pair item into the database.
+ */
+ public boolean putStoredFastPairItem(Cache.StoredFastPairItem storedFastPairItem) {
+ SQLiteDatabase db = mFastPairDbHelper.getWritableDatabase();
+ ContentValues values = new ContentValues();
+ values.put(StoredFastPairItemContract.StoredFastPairItemEntry.COLUMN_MAC_ADDRESS,
+ storedFastPairItem.getMacAddress());
+ values.put(StoredFastPairItemContract.StoredFastPairItemEntry.COLUMN_ACCOUNT_KEY,
+ storedFastPairItem.getAccountKey().toString());
+ values.put(StoredFastPairItemContract.StoredFastPairItemEntry.COLUMN_STORED_FAST_PAIR_BYTE,
+ storedFastPairItem.toByteArray());
+ db.insert(StoredFastPairItemContract.StoredFastPairItemEntry.TABLE_NAME, null, values);
+ return true;
+
+ }
+
+ /**
+ * Removes certain storedFastPairItem so that it can update timely.
+ */
+ public void removeStoredFastPairItem(String macAddress) {
+ SQLiteDatabase db = mFastPairDbHelper.getWritableDatabase();
+ int res = db.delete(StoredFastPairItemContract.StoredFastPairItemEntry.TABLE_NAME,
+ StoredFastPairItemContract.StoredFastPairItemEntry.COLUMN_MAC_ADDRESS + "=?",
+ new String[]{macAddress});
+
+ }
+
+ /**
+ * Get all of the store fast pair item related info in the cache.
+ */
+ public List<Cache.StoredFastPairItem> getAllSavedStoredFastPairItem() {
+ List<Cache.StoredFastPairItem> storedFastPairItemList = new ArrayList<>();
+ SQLiteDatabase db = mFastPairDbHelper.getReadableDatabase();
+ String[] projection = {
+ StoredFastPairItemContract.StoredFastPairItemEntry.COLUMN_MAC_ADDRESS,
+ StoredFastPairItemContract.StoredFastPairItemEntry.COLUMN_ACCOUNT_KEY,
+ StoredFastPairItemContract.StoredFastPairItemEntry.COLUMN_STORED_FAST_PAIR_BYTE
+ };
+ Cursor cursor = db.query(
+ StoredFastPairItemContract.StoredFastPairItemEntry.TABLE_NAME,
+ projection,
+ null,
+ null,
+ null,
+ null,
+ null
+ );
+
+ while (cursor.moveToNext()) {
+ byte[] res = cursor.getBlob(cursor.getColumnIndexOrThrow(StoredFastPairItemContract
+ .StoredFastPairItemEntry.COLUMN_STORED_FAST_PAIR_BYTE));
+ try {
+ Cache.StoredFastPairItem item = Cache.StoredFastPairItem.parseFrom(res);
+ storedFastPairItemList.add(item);
+ } catch (InvalidProtocolBufferException e) {
+ Log.e("FastPairCacheManager", "storediscovery has error");
+ }
+
+ }
+ cursor.close();
+ return storedFastPairItemList;
+ }
}
diff --git a/nearby/service/java/com/android/server/nearby/fastpair/cache/FastPairDbHelper.java b/nearby/service/java/com/android/server/nearby/fastpair/cache/FastPairDbHelper.java
new file mode 100644
index 0000000..d950d8d
--- /dev/null
+++ b/nearby/service/java/com/android/server/nearby/fastpair/cache/FastPairDbHelper.java
@@ -0,0 +1,76 @@
+/*
+ * 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.fastpair.cache;
+
+import android.content.Context;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteOpenHelper;
+
+/**
+ * Fast Pair db helper handle all of the db actions related Fast Pair.
+ */
+public class FastPairDbHelper extends SQLiteOpenHelper {
+
+ public static final int DATABASE_VERSION = 1;
+ public static final String DATABASE_NAME = "FastPair.db";
+ private static final String SQL_CREATE_DISCOVERY_ITEM_DB =
+ "CREATE TABLE IF NOT EXISTS " + DiscoveryItemContract.DiscoveryItemEntry.TABLE_NAME
+ + " (" + DiscoveryItemContract.DiscoveryItemEntry._ID
+ + "INTEGER PRIMARY KEY,"
+ + DiscoveryItemContract.DiscoveryItemEntry.COLUMN_MODEL_ID
+ + " TEXT," + DiscoveryItemContract.DiscoveryItemEntry.COLUMN_SCAN_BYTE
+ + " BLOB)";
+ private static final String SQL_DELETE_DISCOVERY_ITEM_DB =
+ "DROP TABLE IF EXISTS " + DiscoveryItemContract.DiscoveryItemEntry.TABLE_NAME;
+ private static final String SQL_CREATE_FAST_PAIR_ITEM_DB =
+ "CREATE TABLE IF NOT EXISTS "
+ + StoredFastPairItemContract.StoredFastPairItemEntry.TABLE_NAME
+ + " (" + StoredFastPairItemContract.StoredFastPairItemEntry._ID
+ + "INTEGER PRIMARY KEY,"
+ + StoredFastPairItemContract.StoredFastPairItemEntry.COLUMN_MAC_ADDRESS
+ + " TEXT,"
+ + StoredFastPairItemContract.StoredFastPairItemEntry.COLUMN_ACCOUNT_KEY
+ + " TEXT,"
+ + StoredFastPairItemContract
+ .StoredFastPairItemEntry.COLUMN_STORED_FAST_PAIR_BYTE
+ + " BLOB)";
+ private static final String SQL_DELETE_FAST_PAIR_ITEM_DB =
+ "DROP TABLE IF EXISTS " + StoredFastPairItemContract.StoredFastPairItemEntry.TABLE_NAME;
+
+ public FastPairDbHelper(Context context) {
+ super(context, DATABASE_NAME, null, DATABASE_VERSION);
+ }
+
+ @Override
+ public void onCreate(SQLiteDatabase db) {
+ db.execSQL(SQL_CREATE_DISCOVERY_ITEM_DB);
+ db.execSQL(SQL_CREATE_FAST_PAIR_ITEM_DB);
+ }
+
+ @Override
+ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+ // Since the outdated data has no value so just remove the data.
+ db.execSQL(SQL_DELETE_DISCOVERY_ITEM_DB);
+ db.execSQL(SQL_DELETE_FAST_PAIR_ITEM_DB);
+ onCreate(db);
+ }
+
+ @Override
+ public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+ super.onDowngrade(db, oldVersion, newVersion);
+ }
+}
diff --git a/nearby/service/java/com/android/server/nearby/fastpair/cache/StoredFastPairItemContract.java b/nearby/service/java/com/android/server/nearby/fastpair/cache/StoredFastPairItemContract.java
new file mode 100644
index 0000000..9980565
--- /dev/null
+++ b/nearby/service/java/com/android/server/nearby/fastpair/cache/StoredFastPairItemContract.java
@@ -0,0 +1,37 @@
+/*
+ * 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.fastpair.cache;
+
+import android.provider.BaseColumns;
+
+/**
+ * Defines fast pair item database schema.
+ */
+public class StoredFastPairItemContract {
+ private StoredFastPairItemContract() {}
+
+ /**
+ * StoredFastPairItem entry related info.
+ */
+ public static class StoredFastPairItemEntry implements BaseColumns {
+ public static final String TABLE_NAME = "STORED_FAST_PAIR_ITEM";
+ public static final String COLUMN_MAC_ADDRESS = "MAC_ADDRESS";
+ public static final String COLUMN_ACCOUNT_KEY = "ACCOUNT_KEY";
+
+ public static final String COLUMN_STORED_FAST_PAIR_BYTE = "STORED_FAST_PAIR_BYTE";
+ }
+}
diff --git a/nearby/tests/unit/src/com/android/server/nearby/fastpair/cache/FastPairCacheManagerTest.java b/nearby/tests/unit/src/com/android/server/nearby/fastpair/cache/FastPairCacheManagerTest.java
index b8233ec..adae97d 100644
--- a/nearby/tests/unit/src/com/android/server/nearby/fastpair/cache/FastPairCacheManagerTest.java
+++ b/nearby/tests/unit/src/com/android/server/nearby/fastpair/cache/FastPairCacheManagerTest.java
@@ -25,6 +25,8 @@
import androidx.test.core.app.ApplicationProvider;
import androidx.test.filters.SdkSuppress;
+import com.google.protobuf.ByteString;
+
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
@@ -37,9 +39,17 @@
private static final String MODEL_ID = "001";
private static final String MODEL_ID2 = "002";
private static final String APP_NAME = "APP_NAME";
+ private static final String MAC_ADDRESS = "00:11:22:33";
+ private static final ByteString ACCOUNT_KEY = ByteString.copyFromUtf8("axgs");
+ private static final String MAC_ADDRESS_B = "00:11:22:44";
+ private static final ByteString ACCOUNT_KEY_B = ByteString.copyFromUtf8("axgb");
+
@Mock
DiscoveryItem mDiscoveryItem;
- @Mock DiscoveryItem mDiscoveryItem2;
+ @Mock
+ DiscoveryItem mDiscoveryItem2;
+ @Mock
+ Cache.StoredFastPairItem mStoredFastPairItem;
Cache.StoredDiscoveryItem mStoredDiscoveryItem = Cache.StoredDiscoveryItem.newBuilder()
.setTriggerId(MODEL_ID)
.setAppName(APP_NAME).build();
@@ -97,4 +107,47 @@
assertThat(fastPairCacheManager.getAllSavedStoreDiscoveryItem()).hasSize(3);
}
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void saveRetrieveInfoStoredFastPairItem() {
+ Context mContext = ApplicationProvider.getApplicationContext();
+ Cache.StoredFastPairItem storedFastPairItem = Cache.StoredFastPairItem.newBuilder()
+ .setMacAddress(MAC_ADDRESS)
+ .setAccountKey(ACCOUNT_KEY)
+ .build();
+
+
+ FastPairCacheManager fastPairCacheManager = new FastPairCacheManager(mContext);
+ fastPairCacheManager.putStoredFastPairItem(storedFastPairItem);
+
+ assertThat(fastPairCacheManager.getStoredFastPairItemFromMacAddress(
+ MAC_ADDRESS).getAccountKey())
+ .isEqualTo(ACCOUNT_KEY);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
+ public void checkGetAllFastPairItems() {
+ Context mContext = ApplicationProvider.getApplicationContext();
+ Cache.StoredFastPairItem storedFastPairItem = Cache.StoredFastPairItem.newBuilder()
+ .setMacAddress(MAC_ADDRESS)
+ .setAccountKey(ACCOUNT_KEY)
+ .build();
+ Cache.StoredFastPairItem storedFastPairItemB = Cache.StoredFastPairItem.newBuilder()
+ .setMacAddress(MAC_ADDRESS_B)
+ .setAccountKey(ACCOUNT_KEY_B)
+ .build();
+
+ FastPairCacheManager fastPairCacheManager = new FastPairCacheManager(mContext);
+ fastPairCacheManager.putStoredFastPairItem(storedFastPairItem);
+ fastPairCacheManager.putStoredFastPairItem(storedFastPairItemB);
+
+ assertThat(fastPairCacheManager.getAllSavedStoredFastPairItem().size())
+ .isEqualTo(2);
+
+ fastPairCacheManager.removeStoredFastPairItem(MAC_ADDRESS_B);
+
+ assertThat(fastPairCacheManager.getAllSavedStoredFastPairItem().size())
+ .isEqualTo(1);
+ }
}