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.cache; 18 19 import android.bluetooth.le.ScanResult; 20 import android.content.ContentValues; 21 import android.content.Context; 22 import android.database.Cursor; 23 import android.database.sqlite.SQLiteDatabase; 24 import android.util.Log; 25 26 import com.android.server.nearby.common.eventloop.Annotations; 27 28 import com.google.protobuf.InvalidProtocolBufferException; 29 30 import java.util.ArrayList; 31 import java.util.List; 32 33 import service.proto.Cache; 34 import service.proto.Rpcs; 35 36 37 /** 38 * Save FastPair device info to database to avoid multiple requesting. 39 */ 40 public class FastPairCacheManager { 41 private final Context mContext; 42 private final FastPairDbHelper mFastPairDbHelper; 43 FastPairCacheManager(Context context)44 public FastPairCacheManager(Context context) { 45 mContext = context; 46 mFastPairDbHelper = new FastPairDbHelper(context); 47 } 48 49 /** 50 * Clean up function to release db 51 */ cleanUp()52 public void cleanUp() { 53 mFastPairDbHelper.close(); 54 } 55 56 /** 57 * Saves the response to the db 58 */ saveDevice()59 private void saveDevice() { 60 } 61 getDeviceFromScanResult(ScanResult scanResult)62 Cache.ServerResponseDbItem getDeviceFromScanResult(ScanResult scanResult) { 63 return Cache.ServerResponseDbItem.newBuilder().build(); 64 } 65 66 /** 67 * Checks if the entry can be auto deleted from the cache 68 */ isDeletable(Cache.ServerResponseDbItem entry)69 public boolean isDeletable(Cache.ServerResponseDbItem entry) { 70 if (!entry.getExpirable()) { 71 return false; 72 } 73 return true; 74 } 75 76 /** 77 * Save discovery item into database. Discovery item is item that discovered through Ble before 78 * pairing success. 79 */ saveDiscoveryItem(DiscoveryItem item)80 public boolean saveDiscoveryItem(DiscoveryItem item) { 81 82 SQLiteDatabase db = mFastPairDbHelper.getWritableDatabase(); 83 ContentValues values = new ContentValues(); 84 values.put(DiscoveryItemContract.DiscoveryItemEntry.COLUMN_MODEL_ID, item.getTriggerId()); 85 values.put(DiscoveryItemContract.DiscoveryItemEntry.COLUMN_SCAN_BYTE, 86 item.getCopyOfStoredItem().toByteArray()); 87 db.insert(DiscoveryItemContract.DiscoveryItemEntry.TABLE_NAME, null, values); 88 return true; 89 } 90 91 92 @Annotations.EventThread getObservedDeviceInfo(ScanResult scanResult)93 private Rpcs.GetObservedDeviceResponse getObservedDeviceInfo(ScanResult scanResult) { 94 return Rpcs.GetObservedDeviceResponse.getDefaultInstance(); 95 } 96 97 /** 98 * Get discovery item from item id. 99 */ getDiscoveryItem(String itemId)100 public DiscoveryItem getDiscoveryItem(String itemId) { 101 return new DiscoveryItem(mContext, getStoredDiscoveryItem(itemId)); 102 } 103 104 /** 105 * Get discovery item from item id. 106 */ getStoredDiscoveryItem(String itemId)107 public Cache.StoredDiscoveryItem getStoredDiscoveryItem(String itemId) { 108 SQLiteDatabase db = mFastPairDbHelper.getReadableDatabase(); 109 String[] projection = { 110 DiscoveryItemContract.DiscoveryItemEntry.COLUMN_MODEL_ID, 111 DiscoveryItemContract.DiscoveryItemEntry.COLUMN_SCAN_BYTE 112 }; 113 String selection = DiscoveryItemContract.DiscoveryItemEntry.COLUMN_MODEL_ID + " =? "; 114 String[] selectionArgs = {itemId}; 115 Cursor cursor = db.query( 116 DiscoveryItemContract.DiscoveryItemEntry.TABLE_NAME, 117 projection, 118 selection, 119 selectionArgs, 120 null, 121 null, 122 null 123 ); 124 125 if (cursor.moveToNext()) { 126 byte[] res = cursor.getBlob(cursor.getColumnIndexOrThrow( 127 DiscoveryItemContract.DiscoveryItemEntry.COLUMN_SCAN_BYTE)); 128 try { 129 Cache.StoredDiscoveryItem item = Cache.StoredDiscoveryItem.parseFrom(res); 130 return item; 131 } catch (InvalidProtocolBufferException e) { 132 Log.e("FastPairCacheManager", "storediscovery has error"); 133 } 134 } 135 cursor.close(); 136 return Cache.StoredDiscoveryItem.getDefaultInstance(); 137 } 138 139 /** 140 * Get all of the discovery item related info in the cache. 141 */ getAllSavedStoreDiscoveryItem()142 public List<Cache.StoredDiscoveryItem> getAllSavedStoreDiscoveryItem() { 143 List<Cache.StoredDiscoveryItem> storedDiscoveryItemList = new ArrayList<>(); 144 SQLiteDatabase db = mFastPairDbHelper.getReadableDatabase(); 145 String[] projection = { 146 DiscoveryItemContract.DiscoveryItemEntry.COLUMN_MODEL_ID, 147 DiscoveryItemContract.DiscoveryItemEntry.COLUMN_SCAN_BYTE 148 }; 149 Cursor cursor = db.query( 150 DiscoveryItemContract.DiscoveryItemEntry.TABLE_NAME, 151 projection, 152 null, 153 null, 154 null, 155 null, 156 null 157 ); 158 159 while (cursor.moveToNext()) { 160 byte[] res = cursor.getBlob(cursor.getColumnIndexOrThrow( 161 DiscoveryItemContract.DiscoveryItemEntry.COLUMN_SCAN_BYTE)); 162 try { 163 Cache.StoredDiscoveryItem item = Cache.StoredDiscoveryItem.parseFrom(res); 164 storedDiscoveryItemList.add(item); 165 } catch (InvalidProtocolBufferException e) { 166 Log.e("FastPairCacheManager", "storediscovery has error"); 167 } 168 169 } 170 cursor.close(); 171 return storedDiscoveryItemList; 172 } 173 174 /** 175 * Get scan result from local database use model id 176 */ getStoredScanResult(String modelId)177 public Cache.StoredScanResult getStoredScanResult(String modelId) { 178 return Cache.StoredScanResult.getDefaultInstance(); 179 } 180 181 /** 182 * Gets the paired Fast Pair item that paired to the phone through mac address. 183 */ getStoredFastPairItemFromMacAddress(String macAddress)184 public Cache.StoredFastPairItem getStoredFastPairItemFromMacAddress(String macAddress) { 185 SQLiteDatabase db = mFastPairDbHelper.getReadableDatabase(); 186 String[] projection = { 187 StoredFastPairItemContract.StoredFastPairItemEntry.COLUMN_ACCOUNT_KEY, 188 StoredFastPairItemContract.StoredFastPairItemEntry.COLUMN_MAC_ADDRESS, 189 StoredFastPairItemContract.StoredFastPairItemEntry.COLUMN_STORED_FAST_PAIR_BYTE 190 }; 191 String selection = 192 StoredFastPairItemContract.StoredFastPairItemEntry.COLUMN_MAC_ADDRESS + " =? "; 193 String[] selectionArgs = {macAddress}; 194 Cursor cursor = db.query( 195 StoredFastPairItemContract.StoredFastPairItemEntry.TABLE_NAME, 196 projection, 197 selection, 198 selectionArgs, 199 null, 200 null, 201 null 202 ); 203 204 if (cursor.moveToNext()) { 205 byte[] res = cursor.getBlob(cursor.getColumnIndexOrThrow( 206 StoredFastPairItemContract.StoredFastPairItemEntry 207 .COLUMN_STORED_FAST_PAIR_BYTE)); 208 try { 209 Cache.StoredFastPairItem item = Cache.StoredFastPairItem.parseFrom(res); 210 return item; 211 } catch (InvalidProtocolBufferException e) { 212 Log.e("FastPairCacheManager", "storediscovery has error"); 213 } 214 } 215 cursor.close(); 216 return Cache.StoredFastPairItem.getDefaultInstance(); 217 } 218 219 /** 220 * Save paired fast pair item into the database. 221 */ putStoredFastPairItem(Cache.StoredFastPairItem storedFastPairItem)222 public boolean putStoredFastPairItem(Cache.StoredFastPairItem storedFastPairItem) { 223 SQLiteDatabase db = mFastPairDbHelper.getWritableDatabase(); 224 ContentValues values = new ContentValues(); 225 values.put(StoredFastPairItemContract.StoredFastPairItemEntry.COLUMN_MAC_ADDRESS, 226 storedFastPairItem.getMacAddress()); 227 values.put(StoredFastPairItemContract.StoredFastPairItemEntry.COLUMN_ACCOUNT_KEY, 228 storedFastPairItem.getAccountKey().toString()); 229 values.put(StoredFastPairItemContract.StoredFastPairItemEntry.COLUMN_STORED_FAST_PAIR_BYTE, 230 storedFastPairItem.toByteArray()); 231 db.insert(StoredFastPairItemContract.StoredFastPairItemEntry.TABLE_NAME, null, values); 232 return true; 233 234 } 235 236 /** 237 * Removes certain storedFastPairItem so that it can update timely. 238 */ removeStoredFastPairItem(String macAddress)239 public void removeStoredFastPairItem(String macAddress) { 240 SQLiteDatabase db = mFastPairDbHelper.getWritableDatabase(); 241 int res = db.delete(StoredFastPairItemContract.StoredFastPairItemEntry.TABLE_NAME, 242 StoredFastPairItemContract.StoredFastPairItemEntry.COLUMN_MAC_ADDRESS + "=?", 243 new String[]{macAddress}); 244 245 } 246 247 /** 248 * Get all of the store fast pair item related info in the cache. 249 */ getAllSavedStoredFastPairItem()250 public List<Cache.StoredFastPairItem> getAllSavedStoredFastPairItem() { 251 List<Cache.StoredFastPairItem> storedFastPairItemList = new ArrayList<>(); 252 SQLiteDatabase db = mFastPairDbHelper.getReadableDatabase(); 253 String[] projection = { 254 StoredFastPairItemContract.StoredFastPairItemEntry.COLUMN_MAC_ADDRESS, 255 StoredFastPairItemContract.StoredFastPairItemEntry.COLUMN_ACCOUNT_KEY, 256 StoredFastPairItemContract.StoredFastPairItemEntry.COLUMN_STORED_FAST_PAIR_BYTE 257 }; 258 Cursor cursor = db.query( 259 StoredFastPairItemContract.StoredFastPairItemEntry.TABLE_NAME, 260 projection, 261 null, 262 null, 263 null, 264 null, 265 null 266 ); 267 268 while (cursor.moveToNext()) { 269 byte[] res = cursor.getBlob(cursor.getColumnIndexOrThrow(StoredFastPairItemContract 270 .StoredFastPairItemEntry.COLUMN_STORED_FAST_PAIR_BYTE)); 271 try { 272 Cache.StoredFastPairItem item = Cache.StoredFastPairItem.parseFrom(res); 273 storedFastPairItemList.add(item); 274 } catch (InvalidProtocolBufferException e) { 275 Log.e("FastPairCacheManager", "storediscovery has error"); 276 } 277 278 } 279 cursor.close(); 280 return storedFastPairItemList; 281 } 282 } 283